<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus';

import type {
  SkillCategory,
  SkillGitCandidate,
  SkillGitScanResult,
  SkillImportPreview,
  SkillInfo,
  SkillVisibilityScope,
} from './types';

import { computed, nextTick, reactive, ref, watch } from 'vue';

import {
  Check,
  Document,
  Link,
  Plus,
  Search,
  UploadFilled,
} from '@element-plus/icons-vue';
import {
  ElButton,
  ElDialog,
  ElForm,
  ElFormItem,
  ElIcon,
  ElInput,
  ElMessage,
  ElOption,
  ElRadioButton,
  ElRadioGroup,
  ElSelect,
  ElTag,
} from 'element-plus';

import {
  cancelSkillImport,
  importSkillConfirmBatch,
  importSkillPreviews,
  prepareSkillGitCandidates,
  saveSkill,
  scanSkillGitRepository,
} from './api';
import { resolveSkillApiErrorMessage } from './skill-api-error';
import { flattenSkillCategories } from './skill-category';
import { buildInitialSkillDraft } from './skill-create';

type CreateMode = 'import' | 'manual';
type ConflictStrategy = 'OVERWRITE' | 'REJECT' | 'RENAME';
type ImportSource = 'git' | 'zip';

interface ImportRow {
  key: string;
  label: string;
  message?: string;
  preview?: SkillImportPreview;
  rename: string;
  result?: 'failed' | 'success';
  strategy: ConflictStrategy;
}

const props = withDefaults(
  defineProps<{
    categories: SkillCategory[];
    categoriesLoading?: boolean;
    defaultCategoryId?: number | string;
    defaultMode?: CreateMode;
    modelValue: boolean;
  }>(),
  {
    categoriesLoading: false,
    defaultCategoryId: '',
    defaultMode: 'manual',
  },
);

const emit = defineEmits<{
  created: [skill: SkillInfo];
  imported: [count: number];
  'update:modelValue': [value: boolean];
}>();

const MAX_IMPORT_SKILLS = 50;

const formRef = ref<FormInstance>();
const nameInputRef = ref<InstanceType<typeof ElInput>>();
const fileInputRef = ref<HTMLInputElement>();
const mode = ref<CreateMode>('manual');
const importSource = ref<ImportSource>('zip');
const busy = ref(false);
const actionError = ref('');
const importRows = ref<ImportRow[]>([]);
const importFinished = ref(false);
const gitRepositoryUrl = ref('');
const gitSearch = ref('');
const gitScan = ref<SkillGitScanResult>();
const selectedGitCandidateIds = ref<Set<string>>(new Set());
const form = reactive({
  categoryId: '' as number | string,
  displayName: '',
  visibilityScope: 'PRIVATE' as SkillVisibilityScope,
});

const visible = computed({
  get: () => props.modelValue,
  set: (value) => {
    if (!value && busy.value) {
      ElMessage.info('请等待当前操作完成');
      return;
    }
    emit('update:modelValue', value);
  },
});
const categoryOptions = computed(() =>
  flattenSkillCategories(props.categories),
);
const rules: FormRules = {
  displayName: [
    { message: '请输入技能名称', required: true, trigger: 'blur' },
    { max: 128, message: '技能名称不能超过 128 个字符', trigger: 'blur' },
  ],
};
const confirmText = computed(() => {
  if (mode.value === 'manual') return '创建并进入编辑';
  if (importSource.value !== 'git' || importRows.value.length > 0)
    return '导入';
  const count = selectedGitCandidateIds.value.size;
  return `导入所选${count > 0 ? `（${count}）` : ''}`;
});
const dialogWidth = computed(() =>
  mode.value === 'import' && importSource.value === 'git'
    ? 'min(920px, calc(100vw - 32px))'
    : 'min(720px, calc(100vw - 32px))',
);
const importReady = computed(
  () => importRows.value.length > 0 && rowsReady(importRows.value),
);
const filteredGitCandidates = computed(() => {
  const keyword = normalizeSearch(gitSearch.value);
  if (!keyword) return gitScan.value?.candidates || [];
  return (gitScan.value?.candidates || []).filter((candidate) =>
    normalizeSearch(
      `${candidate.name} ${candidate.description || ''} ${candidate.path}`,
    ).includes(keyword),
  );
});
const submitDisabled = computed(() => {
  if (mode.value === 'manual') return false;
  if (importRows.value.length > 0) return !importReady.value;
  return (
    importSource.value === 'zip' || selectedGitCandidateIds.value.size === 0
  );
});

watch(
  () => props.modelValue,
  (open) => {
    if (!open) return;
    mode.value = props.defaultMode;
    importSource.value = 'zip';
    Object.assign(form, {
      categoryId: props.defaultCategoryId || '',
      displayName: '',
      visibilityScope: 'PRIVATE',
    });
    importRows.value = [];
    importFinished.value = false;
    gitRepositoryUrl.value = '';
    gitSearch.value = '';
    gitScan.value = undefined;
    selectedGitCandidateIds.value = new Set();
    actionError.value = '';
    formRef.value?.clearValidate();
    if (mode.value === 'manual')
      void nextTick(() => nameInputRef.value?.focus());
  },
  { immediate: true },
);

async function submit() {
  if (busy.value) return;
  if (mode.value === 'manual') {
    await createManualSkill();
  } else if (importSource.value === 'git' && importRows.value.length === 0) {
    await prepareGitImports();
  } else {
    await confirmImports();
  }
}

async function createManualSkill() {
  form.displayName = form.displayName.trim();
  if (!(await formRef.value?.validate().catch(() => false))) return;
  busy.value = true;
  actionError.value = '';
  try {
    const response = await saveSkill(buildInitialSkillDraft(form));
    if (response.errorCode !== 0 || !response.data?.id) {
      actionError.value = response.message || '技能创建失败，请重试';
      return;
    }
    emit('update:modelValue', false);
    emit('created', response.data);
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '技能创建失败，请重试',
    );
  } finally {
    busy.value = false;
  }
}

function chooseFiles() {
  if (!busy.value) fileInputRef.value?.click();
}

async function handleFiles(event: Event) {
  const input = event.target as HTMLInputElement;
  const files = [...(input.files || [])];
  input.value = '';
  await previewFiles(files);
}

async function handleDrop(event: DragEvent) {
  event.preventDefault();
  await previewFiles([...(event.dataTransfer?.files || [])]);
}

async function previewFiles(files: File[]) {
  if (busy.value || files.length === 0) return;
  if (files.length > MAX_IMPORT_SKILLS) {
    ElMessage.warning(`单次最多选择 ${MAX_IMPORT_SKILLS} 个 ZIP`);
    return;
  }
  if (files.some((file) => !file.name.toLowerCase().endsWith('.zip'))) {
    ElMessage.warning('仅支持标准 Skill ZIP');
    return;
  }
  await cancelPendingImports();
  busy.value = true;
  actionError.value = '';
  try {
    const response = await importSkillPreviews(files);
    if (response.errorCode !== 0) {
      actionError.value = response.message || '导入预检失败';
      return;
    }
    importRows.value = response.data.map((preview, index) => {
      const item = preview?.skills[0];
      const sourceName = preview?.sourceName || `导入包 ${index + 1}`;
      return {
        key:
          preview?.importToken ||
          `${sourceName}-${item?.packageRoot || item?.packageId || 'invalid'}-${index}`,
        label: sourceName,
        preview,
        rename: item ? `${item.name}-copy` : '',
        strategy: item?.conflict ? 'RENAME' : 'REJECT',
      };
    });
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '导入预检失败，请重试',
    );
  } finally {
    busy.value = false;
  }
}

async function confirmImports() {
  if (!importReady.value) {
    ElMessage.warning('请先处理导入错误和名称冲突');
    return;
  }
  await confirmImportRows(importRows.value);
}

async function confirmImportRows(rows: ImportRow[]) {
  busy.value = true;
  actionError.value = '';
  try {
    const response = await importSkillConfirmBatch(
      rows.map((row) => {
        const item = row.preview!.skills[0]!;
        return {
          categoryId: form.categoryId || undefined,
          conflictStrategy: row.strategy,
          importToken: row.preview!.importToken!,
          renames:
            row.strategy === 'RENAME'
              ? { [item.packageRoot || item.packageId]: row.rename.trim() }
              : undefined,
          visibilityScope: form.visibilityScope,
        };
      }),
    );
    if (response.errorCode !== 0) {
      actionError.value = response.message || '导入失败';
      return;
    }
    let succeeded = 0;
    response.data.forEach((result, index) => {
      const row = rows[index];
      if (!row) return;
      row.result = result.success ? 'success' : 'failed';
      row.message = result.message;
      if (result.success) succeeded += result.skills.length;
    });
    importFinished.value = true;
    emit('imported', succeeded);
    if (succeeded === rows.length) {
      ElMessage.success(`已导入 ${succeeded} 个技能`);
      emit('update:modelValue', false);
    }
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(error, '导入失败，请重试');
  } finally {
    busy.value = false;
  }
}

async function scanGitRepo() {
  if (busy.value) return;
  const repositoryUrl = gitRepositoryUrl.value.trim();
  if (!repositoryUrl) {
    ElMessage.warning('请输入 Git 仓库地址');
    return;
  }
  await cancelPendingImports();
  busy.value = true;
  actionError.value = '';
  importRows.value = [];
  importFinished.value = false;
  selectedGitCandidateIds.value = new Set();
  try {
    const response = await scanSkillGitRepository(repositoryUrl);
    if (response.errorCode !== 0 || !response.data?.scanToken) {
      actionError.value = response.message || '仓库扫描失败';
      gitScan.value = undefined;
      return;
    }
    gitScan.value = response.data;
    if (response.data.summary.discovered === 0) {
      ElMessage.info('仓库中未发现 SKILL.md');
    }
  } catch (error) {
    gitScan.value = undefined;
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '仓库扫描失败，请检查地址后重试',
    );
  } finally {
    busy.value = false;
  }
}

function toggleGitCandidate(candidate: SkillGitCandidate) {
  if (candidate.status !== 'IMPORTABLE' || busy.value) return;
  const next = new Set(selectedGitCandidateIds.value);
  if (next.has(candidate.candidateId)) {
    next.delete(candidate.candidateId);
  } else if (next.size >= MAX_IMPORT_SKILLS) {
    ElMessage.warning(`单次最多导入 ${MAX_IMPORT_SKILLS} 个技能`);
    return;
  } else {
    next.add(candidate.candidateId);
  }
  selectedGitCandidateIds.value = next;
}

async function prepareGitImports() {
  const scan = gitScan.value;
  const selected = scan?.candidates.filter((candidate) =>
    selectedGitCandidateIds.value.has(candidate.candidateId),
  );
  if (!scan || !selected?.length) {
    ElMessage.warning('请先扫描并选择要导入的技能');
    return;
  }
  busy.value = true;
  actionError.value = '';
  try {
    const response = await prepareSkillGitCandidates(
      scan.scanToken,
      selected.map((candidate) => candidate.candidateId),
    );
    if (response.errorCode !== 0) {
      actionError.value = response.message || '准备导入失败';
      return;
    }
    const rows = selected.map((candidate, index): ImportRow => {
      const preview = response.data[index];
      const item = preview?.skills[0];
      return {
        key: candidate.candidateId,
        label: candidate.path,
        preview,
        rename: item ? `${item.name}-copy` : '',
        strategy: item?.conflict ? 'RENAME' : 'REJECT',
      };
    });
    importRows.value = rows;
    if (rowsReady(rows)) {
      busy.value = false;
      await confirmImportRows(rows);
    }
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '准备导入失败，请重新扫描',
    );
  } finally {
    busy.value = false;
  }
}

async function requestClose() {
  if (busy.value) return;
  await cancelPendingImports();
  emit('update:modelValue', false);
}

async function cancelPendingImports() {
  if (importFinished.value) return;
  const tokens = importRows.value
    .map((row) => row.preview?.importToken)
    .filter((token): token is string => typeof token === 'string');
  await Promise.all(
    tokens.map((token) => cancelSkillImport(token).catch(() => undefined)),
  );
}

function importErrorCount(preview?: SkillImportPreview) {
  return (preview?.issues || []).filter((issue) => issue.severity === 'ERROR')
    .length;
}

function rowsReady(rows: ImportRow[]) {
  return rows.every((row) => {
    const item = row.preview?.skills[0];
    if (!row.preview?.importToken || !item || importErrorCount(row.preview))
      return false;
    if (!item.conflict) return true;
    if (row.strategy === 'OVERWRITE') return item.overwriteAllowed === true;
    if (row.strategy === 'RENAME') return canonicalName(row.rename);
    return false;
  });
}

function normalizeSearch(value: string) {
  return value.trim().toLocaleLowerCase().replaceAll(/\s+/g, ' ');
}

function formatBytes(bytes: number) {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${Math.ceil(bytes / 1024)} KB`;
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
}

function canonicalName(value: string) {
  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value.trim());
}

function scopeLabel(scope: SkillVisibilityScope) {
  return { DEPT: '部门', PRIVATE: '个人', PUBLIC: '全部' }[scope];
}
</script>

<template>
  <ElDialog
    v-model="visible"
    class="skill-create-dialog"
    :width="dialogWidth"
    :close-on-click-modal="false"
    :close-on-press-escape="!busy"
    :show-close="!busy"
    title="新建技能"
    @closed="cancelPendingImports"
  >
    <ElRadioGroup v-model="mode" class="skill-create-dialog__mode">
      <ElRadioButton value="manual">自己编写</ElRadioButton>
      <ElRadioButton value="import">批量导入</ElRadioButton>
    </ElRadioGroup>

    <p v-if="actionError" class="skill-create-dialog__error" role="alert">
      {{ actionError }}
    </p>

    <ElForm
      ref="formRef"
      class="skill-create-dialog__form"
      label-position="top"
      :model="form"
      :rules="rules"
    >
      <ElFormItem v-if="mode === 'manual'" label="技能名称" prop="displayName">
        <ElInput
          ref="nameInputRef"
          v-model="form.displayName"
          maxlength="128"
          placeholder="请输入技能名称"
          @keyup.enter="submit"
        />
      </ElFormItem>
      <div class="skill-create-dialog__fields">
        <ElFormItem label="分类">
          <ElSelect
            v-model="form.categoryId"
            clearable
            :loading="categoriesLoading"
            placeholder="未分类"
          >
            <ElOption
              v-for="category in categoryOptions"
              :key="category.id"
              :label="`${'\u3000'.repeat(category.depth)}${category.categoryName}`"
              :value="category.id"
              :disabled="category.status !== 1"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem label="范围">
          <ElSelect v-model="form.visibilityScope">
            <ElOption
              v-for="scope in [
                'PRIVATE',
                'DEPT',
                'PUBLIC',
              ] as SkillVisibilityScope[]"
              :key="scope"
              :label="scopeLabel(scope)"
              :value="scope"
            />
          </ElSelect>
        </ElFormItem>
      </div>
    </ElForm>

    <template v-if="mode === 'import'">
      <ElRadioGroup
        v-model="importSource"
        class="skill-create-dialog__source"
        :disabled="busy || importRows.length > 0"
      >
        <ElRadioButton value="zip">本地 ZIP</ElRadioButton>
        <ElRadioButton value="git">Git 仓库</ElRadioButton>
      </ElRadioGroup>

      <template v-if="importSource === 'zip'">
        <input
          ref="fileInputRef"
          class="skill-create-dialog__file-input"
          type="file"
          accept=".zip,application/zip"
          multiple
          @change="handleFiles"
        />
        <button
          type="button"
          class="skill-create-dialog__dropzone"
          :disabled="busy"
          @click="chooseFiles"
          @dragover.prevent
          @drop="handleDrop"
        >
          <ElIcon><UploadFilled /></ElIcon>
          <span>选择或拖入标准 Skill ZIP</span>
          <small>最多导入 50 个技能，支持单技能或多技能 ZIP</small>
        </button>
      </template>

      <section v-else class="skill-create-dialog__git">
        <div class="skill-create-dialog__git-url">
          <ElInput
            v-model="gitRepositoryUrl"
            clearable
            :disabled="busy"
            placeholder="输入 HTTPS Git 仓库地址"
            @keyup.enter="scanGitRepo"
          >
            <template #prefix>
              <ElIcon><Link /></ElIcon>
            </template>
          </ElInput>
          <ElButton :loading="busy" :disabled="busy" @click="scanGitRepo">
            扫描仓库
          </ElButton>
        </div>

        <template v-if="gitScan">
          <div class="skill-create-dialog__git-summary">
            <div>
              <strong>{{ gitScan.repository.name }}</strong>
              <small>
                {{ gitScan.repository.defaultBranch }} ·
                {{ gitScan.repository.commitSha.slice(0, 8) }}
              </small>
            </div>
            <span>发现 {{ gitScan.summary.discovered }} 个</span>
            <span>可导入 {{ gitScan.summary.importable }} 个</span>
            <span v-if="gitScan.summary.needsAttention">
              需处理 {{ gitScan.summary.needsAttention }} 个
            </span>
          </div>
          <ElInput
            v-model="gitSearch"
            class="skill-create-dialog__git-search"
            clearable
            placeholder="搜索技能名称、用途或路径"
          >
            <template #prefix>
              <ElIcon><Search /></ElIcon>
            </template>
          </ElInput>
          <div class="skill-create-dialog__candidates">
            <article
              v-for="candidate in filteredGitCandidates"
              :key="candidate.candidateId"
              :class="{
                'is-selected': selectedGitCandidateIds.has(
                  candidate.candidateId,
                ),
              }"
            >
              <div class="skill-create-dialog__candidate-main">
                <strong>{{ candidate.name }}</strong>
                <p>{{ candidate.description || '暂无用途说明' }}</p>
                <small>
                  {{ candidate.path }} · {{ candidate.resourceCount }} 个资源 ·
                  {{ formatBytes(candidate.totalBytes) }}
                </small>
                <small
                  v-if="candidate.status === 'NEEDS_ATTENTION'"
                  class="skill-create-dialog__candidate-issue"
                >
                  {{ candidate.issues[0]?.message || '内容需要处理' }}
                </small>
              </div>
              <ElTag
                :type="
                  candidate.status === 'IMPORTABLE' ? 'success' : 'warning'
                "
                effect="plain"
              >
                {{ candidate.status === 'IMPORTABLE' ? '可导入' : '需处理' }}
              </ElTag>
              <button
                type="button"
                class="skill-create-dialog__candidate-toggle"
                :class="{
                  'is-selected': selectedGitCandidateIds.has(
                    candidate.candidateId,
                  ),
                }"
                :disabled="candidate.status !== 'IMPORTABLE' || busy"
                :aria-label="
                  selectedGitCandidateIds.has(candidate.candidateId)
                    ? `取消选择 ${candidate.name}`
                    : `选择 ${candidate.name}`
                "
                @click="toggleGitCandidate(candidate)"
              >
                <ElIcon>
                  <Check
                    v-if="selectedGitCandidateIds.has(candidate.candidateId)"
                  />
                  <Plus v-else />
                </ElIcon>
              </button>
            </article>
            <div
              v-if="filteredGitCandidates.length === 0"
              class="skill-create-dialog__candidate-empty"
            >
              没有匹配的技能
            </div>
          </div>
        </template>
      </section>

      <div v-if="importRows.length > 0" class="skill-create-dialog__imports">
        <article v-for="row in importRows" :key="row.key">
          <ElIcon><Document /></ElIcon>
          <div>
            <strong>{{ row.preview?.skills[0]?.name || row.label }}</strong>
            <small v-if="importErrorCount(row.preview)">
              {{ row.preview?.issues?.[0]?.message || '包内容不符合规范' }}
            </small>
            <small v-else-if="row.result === 'failed'">{{ row.message }}</small>
            <small v-else>{{ row.label }}</small>
          </div>
          <ElTag v-if="row.result === 'success'" type="success" effect="plain">
            成功
          </ElTag>
          <ElTag
            v-else-if="row.result === 'failed'"
            type="danger"
            effect="plain"
          >
            失败
          </ElTag>
          <ElTag
            v-else-if="importErrorCount(row.preview)"
            type="danger"
            effect="plain"
          >
            错误
          </ElTag>
          <template v-else-if="row.preview?.skills[0]?.conflict">
            <ElSelect
              v-model="row.strategy"
              class="skill-create-dialog__strategy"
            >
              <ElOption label="重命名" value="RENAME" />
              <ElOption
                label="覆盖草稿"
                value="OVERWRITE"
                :disabled="!row.preview.skills[0].overwriteAllowed"
              />
            </ElSelect>
            <ElInput
              v-if="row.strategy === 'RENAME'"
              v-model="row.rename"
              class="skill-create-dialog__rename"
              placeholder="新标准名称"
            />
          </template>
          <ElTag v-else type="success" effect="plain">可导入</ElTag>
        </article>
      </div>
    </template>

    <template #footer>
      <ElButton :disabled="busy" @click="requestClose">取消</ElButton>
      <ElButton
        type="primary"
        :loading="busy"
        :disabled="submitDisabled"
        @click="submit"
      >
        {{ confirmText }}
      </ElButton>
    </template>
  </ElDialog>
</template>

<style scoped>
.skill-create-dialog__mode {
  width: 100%;
  margin-bottom: var(--space-5);
}

.skill-create-dialog__mode :deep(.el-radio-button) {
  flex: 1;
}

.skill-create-dialog__mode :deep(.el-radio-button__inner) {
  width: 100%;
}

.skill-create-dialog__error {
  padding: var(--space-3);
  margin: 0 0 var(--space-4);
  color: hsl(var(--destructive));
  background: hsl(var(--destructive) / 8%);
  border-radius: var(--radius-control);
}

.skill-create-dialog__fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.skill-create-dialog__form :deep(.el-select) {
  width: 100%;
}

.skill-create-dialog__file-input {
  display: none;
}

.skill-create-dialog__source {
  margin-bottom: var(--space-4);
}

.skill-create-dialog__dropzone {
  display: grid;
  gap: var(--space-2);
  place-items: center;
  width: 100%;
  min-height: 136px;
  color: hsl(var(--text-muted));
  cursor: pointer;
  background: hsl(var(--surface-subtle));
  border: 1px dashed hsl(var(--line-strong));
  border-radius: var(--radius-panel);
  transition: border-color var(--motion-duration-fast)
    var(--motion-ease-standard);
}

.skill-create-dialog__dropzone:hover,
.skill-create-dialog__dropzone:focus-visible {
  border-color: hsl(var(--primary));
  outline: none;
}

.skill-create-dialog__dropzone .el-icon {
  font-size: 28px;
}

.skill-create-dialog__dropzone span {
  color: hsl(var(--foreground));
  font-weight: 600;
}

.skill-create-dialog__git {
  display: grid;
  gap: var(--space-4);
}

.skill-create-dialog__git-url {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-3);
}

.skill-create-dialog__git-summary {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-4);
  background: hsl(var(--surface-subtle));
  border-radius: var(--radius-control);
}

.skill-create-dialog__git-summary > div {
  display: grid;
  flex: 1;
  min-width: 0;
}

.skill-create-dialog__git-summary small,
.skill-create-dialog__git-summary span {
  color: hsl(var(--text-muted));
  font-size: var(--font-size-xs);
}

.skill-create-dialog__git-summary span {
  white-space: nowrap;
}

.skill-create-dialog__candidates {
  display: grid;
  max-height: 336px;
  overflow: auto;
  border-block: 1px solid hsl(var(--line-subtle));
}

.skill-create-dialog__candidates article {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 36px;
  gap: var(--space-3);
  align-items: center;
  min-height: 88px;
  padding: var(--space-3) var(--space-2) var(--space-3) var(--space-4);
  border-bottom: 1px solid hsl(var(--line-subtle));
  transition:
    background-color var(--motion-duration-fast) var(--motion-ease-standard),
    border-color var(--motion-duration-fast) var(--motion-ease-standard);
}

.skill-create-dialog__candidates article:last-child {
  border-bottom: 0;
}

.skill-create-dialog__candidates article:hover,
.skill-create-dialog__candidates article.is-selected {
  background: hsl(var(--nav-item-active));
}

.skill-create-dialog__candidate-main {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.skill-create-dialog__candidate-main p {
  margin: 0;
  overflow: hidden;
  color: hsl(var(--text-secondary));
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skill-create-dialog__candidate-main small {
  overflow: hidden;
  color: hsl(var(--text-muted));
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skill-create-dialog__candidate-main .skill-create-dialog__candidate-issue {
  color: hsl(var(--warning));
}

.skill-create-dialog__candidate-toggle {
  display: grid;
  width: 32px;
  height: 32px;
  padding: 0;
  color: hsl(var(--text-secondary));
  cursor: pointer;
  background: hsl(var(--surface-default));
  border: 1px solid hsl(var(--line-strong));
  border-radius: 50%;
  place-items: center;
  transition:
    color var(--motion-duration-fast) var(--motion-ease-standard),
    background-color var(--motion-duration-fast) var(--motion-ease-standard),
    border-color var(--motion-duration-fast) var(--motion-ease-standard);
}

.skill-create-dialog__candidate-toggle:hover,
.skill-create-dialog__candidate-toggle:focus-visible,
.skill-create-dialog__candidate-toggle.is-selected {
  color: hsl(var(--primary-foreground));
  background: hsl(var(--primary));
  border-color: hsl(var(--primary));
  outline: none;
}

.skill-create-dialog__candidate-toggle:focus-visible {
  box-shadow: 0 0 0 3px hsl(var(--primary) / 20%);
}

.skill-create-dialog__candidate-toggle:disabled {
  color: hsl(var(--text-disabled));
  cursor: not-allowed;
  background: hsl(var(--surface-subtle));
  border-color: hsl(var(--line-subtle));
}

.skill-create-dialog__candidate-empty {
  display: grid;
  min-height: 112px;
  color: hsl(var(--text-muted));
  place-items: center;
}

.skill-create-dialog__imports {
  display: grid;
  gap: var(--space-2);
  max-height: 264px;
  margin-top: var(--space-4);
  overflow: auto;
}

.skill-create-dialog__imports article {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  min-height: 56px;
  padding: var(--space-3);
  border-bottom: 1px solid hsl(var(--line-subtle));
}

.skill-create-dialog__imports article > div {
  display: grid;
  flex: 1;
  min-width: 0;
}

.skill-create-dialog__imports strong,
.skill-create-dialog__imports small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skill-create-dialog__imports small {
  color: hsl(var(--text-muted));
}

.skill-create-dialog__strategy {
  width: 112px;
}

.skill-create-dialog__rename {
  width: 176px;
}

@media (max-width: 640px) {
  .skill-create-dialog__fields {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .skill-create-dialog__imports article {
    flex-wrap: wrap;
  }

  .skill-create-dialog__git-url {
    grid-template-columns: 1fr;
  }

  .skill-create-dialog__git-summary {
    flex-wrap: wrap;
  }

  .skill-create-dialog__candidates article {
    grid-template-columns: minmax(0, 1fr) 32px;
  }

  .skill-create-dialog__candidates article > .el-tag {
    display: none;
  }
}
</style>
