<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import type {
  ChunkMethod,
  DatasetSplitOptions,
  PreprocessOption,
  ProcessType,
  StructuredProcessOptions,
  UnstructuredPreprocessOption,
  UnstructuredProcessOptions,
} from './types'

const props = defineProps<{
  name: string
  description: string
  processType: ProcessType
  structuredOptions: StructuredProcessOptions
  unstructuredOptions: UnstructuredProcessOptions
}>()

const emit = defineEmits<{
  'update:name': [value: string]
  'update:description': [value: string]
  'update:processType': [value: ProcessType]
  'update:structuredOptions': [value: StructuredProcessOptions]
  'update:unstructuredOptions': [value: UnstructuredProcessOptions]
}>()

const PREPROCESS_OPTIONS: Array<{
  value: PreprocessOption
  label: string
  description: string
}> = [
  { value: 'clean_invalid', label: '清理无效数据', description: '处理空行、空列和残缺行' },
  { value: 'detect_structure', label: '识别表格结构', description: '识别表头、多级表头和合并单元格' },
  { value: 'deduplicate', label: '重复数据去重', description: '删除完全重复或关键字段重复的数据' },
  { value: 'normalize_format', label: '数据格式标准化', description: '统一日期、数字、单位和枚举值格式' },
  { value: 'filter_anomaly', label: '异常数据过滤', description: '过滤乱码、无效内容和异常记录' },
  { value: 'desensitize', label: '敏感信息脱敏', description: '处理姓名、手机号、邮箱等敏感信息' },
]

const SMART_PREPROCESS_OPTIONS: UnstructuredPreprocessOption[] = [
  'clean_invalid_content',
  'detect_document_structure',
  'merge_short_content',
  'filter_low_quality',
  'deduplicate_content',
  'preserve_context',
]

const CHUNK_METHODS: Array<{ value: ChunkMethod; label: string }> = [
  { value: 'semantic', label: '自动语义切分' },
  { value: 'heading', label: '按标题和段落' },
  { value: 'fixed', label: '按固定长度' },
  { value: 'custom', label: '自定义分隔符' },
]

function updateStructuredField<K extends keyof StructuredProcessOptions>(
  field: K,
  value: StructuredProcessOptions[K],
) {
  emit('update:structuredOptions', { ...props.structuredOptions, [field]: value })
}

function updatePreprocessOptions(value: Array<string | number | boolean>) {
  const allowedValues = new Set(PREPROCESS_OPTIONS.map((option) => option.value))
  const preprocessOptions = value.filter(
    (option): option is PreprocessOption => typeof option === 'string' && allowedValues.has(option as PreprocessOption),
  )
  updateStructuredField('preprocessOptions', preprocessOptions)
}

function updateSemanticEnrichment(value: string | number | boolean) {
  updateStructuredField('semanticEnrichment', Boolean(value))
}

function updateDatasetSplit(field: keyof DatasetSplitOptions, value: number | undefined) {
  updateStructuredField('datasetSplit', {
    ...props.structuredOptions.datasetSplit,
    [field]: Math.min(100, Math.max(0, Number(value) || 0)),
  })
}

function updateUnstructuredField<K extends keyof UnstructuredProcessOptions>(
  field: K,
  value: UnstructuredProcessOptions[K],
) {
  emit('update:unstructuredOptions', { ...props.unstructuredOptions, [field]: value })
}

function updateSmartPreprocess(value: string | number | boolean) {
  const enabled = Boolean(value)
  const remainingOptions = props.unstructuredOptions.preprocessOptions.filter(
    (option) => !SMART_PREPROCESS_OPTIONS.includes(option),
  )
  updateUnstructuredField(
    'preprocessOptions',
    enabled ? [...SMART_PREPROCESS_OPTIONS, ...remainingOptions] : remainingOptions,
  )
}

function updateDesensitize(value: string | number | boolean) {
  const preprocessOptions: UnstructuredPreprocessOption[] = props.unstructuredOptions.preprocessOptions.filter(
    (option) => option !== 'desensitize',
  )
  if (Boolean(value)) preprocessOptions.push('desensitize')
  updateUnstructuredField('preprocessOptions', preprocessOptions)
}

function updateSpecialContentProtection(value: string | number | boolean) {
  const enabled = Boolean(value)
  emit('update:unstructuredOptions', {
    ...props.unstructuredOptions,
    preserveTables: enabled,
    preserveCodeBlocks: enabled,
    preserveLists: enabled,
  })
}

const UNSTRUCTURED_NUMBER_LIMITS = {
  chunkSize: { min: 200, max: 2000 },
  chunkOverlap: { min: 0, max: 500 },
  minChunkSize: { min: 20, max: 500 },
  qaPairsPerChunk: { min: 1, max: 3 },
} as const

type UnstructuredNumberField = keyof typeof UNSTRUCTURED_NUMBER_LIMITS

function updateUnstructuredNumber(field: UnstructuredNumberField, value: number | undefined) {
  const limits = UNSTRUCTURED_NUMBER_LIMITS[field]
  const parsedValue = Number(value)
  const nextValue = Number.isFinite(parsedValue) ? parsedValue : limits.min
  updateUnstructuredField(field, Math.min(limits.max, Math.max(limits.min, nextValue)))
}

function updateUnstructuredDatasetSplit(field: keyof DatasetSplitOptions, value: number | undefined) {
  updateUnstructuredField('datasetSplit', {
    ...props.unstructuredOptions.datasetSplit,
    [field]: Math.min(100, Math.max(0, Number(value) || 0)),
  })
}

const formRef = ref<FormInstance>()
const advancedChunkSettingsOpen = ref(props.unstructuredOptions.chunkMethod === 'custom')
const formModel = computed(() => ({
  name: props.name,
  processType: props.processType,
}))

const splitTotal = computed(() => {
  const { train, validation, test } = props.structuredOptions.datasetSplit
  return train + validation + test
})

const unstructuredSplitTotal = computed(() => {
  const { train, validation, test } = props.unstructuredOptions.datasetSplit
  return train + validation + test
})

const smartPreprocessEnabled = computed(() => SMART_PREPROCESS_OPTIONS.every(
  (option) => props.unstructuredOptions.preprocessOptions.includes(option),
))

const desensitizeEnabled = computed(() => (
  props.unstructuredOptions.preprocessOptions.includes('desensitize')
))

const preserveSpecialContentEnabled = computed(() => (
  props.unstructuredOptions.preserveTables
  && props.unstructuredOptions.preserveCodeBlocks
  && props.unstructuredOptions.preserveLists
))

const chunkValidationMessage = computed(() => {
  if (props.unstructuredOptions.chunkOverlap >= props.unstructuredOptions.chunkSize) {
    return '重叠长度必须小于切片长度'
  }
  if (props.unstructuredOptions.minChunkSize > props.unstructuredOptions.chunkSize) {
    return '最小切片长度不能大于切片长度'
  }
  if (
    props.unstructuredOptions.chunkOverlap + props.unstructuredOptions.minChunkSize
    > props.unstructuredOptions.chunkSize
  ) {
    return '重叠长度与最小切片长度之和不能大于切片长度'
  }
  if (props.unstructuredOptions.chunkMethod === 'custom' && !props.unstructuredOptions.customDelimiter.trim()) {
    return '请输入自定义分隔符'
  }
  return ''
})

watch(() => props.unstructuredOptions.chunkMethod, (method) => {
  if (method === 'custom') advancedChunkSettingsOpen.value = true
})

watch(chunkValidationMessage, (message) => {
  if (message) advancedChunkSettingsOpen.value = true
})

const rules: FormRules = {
  name: [
    { required: true, message: '请输入任务名称', trigger: 'blur' },
    { max: 50, message: '任务名称不能超过 50 个字符', trigger: 'blur' },
  ],
  processType: [{ required: true, message: '请选择数据处理类型', trigger: 'change' }],
}

async function validate() {
  if (!formRef.value) return false
  try {
    await formRef.value.validate()
    if (props.processType === 'structured' && splitTotal.value !== 100) return false
    if (props.processType === 'unstructured') {
      if (unstructuredSplitTotal.value !== 100) return false
      if (chunkValidationMessage.value) {
        advancedChunkSettingsOpen.value = true
        return false
      }
    }
    return true
  } catch {
    return false
  }
}

defineExpose({ validate })
</script>

<template>
  <section class="task-setup-step">
    <el-form ref="formRef" :model="formModel" :rules="rules" label-position="top">
      <div class="form-section">
        <h3>基本信息</h3>
        <div class="basic-grid">
          <el-form-item label="任务名称" prop="name" required>
            <el-input
              :model-value="name"
              maxlength="50"
              show-word-limit
              placeholder="例如：金融问答清洗任务"
              @update:model-value="emit('update:name', $event)"
            />
          </el-form-item>
          <el-form-item label="任务描述（选填）">
            <el-input
              :model-value="description"
              type="textarea"
              :rows="3"
              maxlength="200"
              show-word-limit
              placeholder="简要说明本次数据处理目标"
              @update:model-value="emit('update:description', $event)"
            />
          </el-form-item>
        </div>
      </div>

      <div class="form-section">
        <div class="section-title-row">
          <div>
            <h3>处理类型</h3>
            <p>类型会影响下一步支持的数据源格式和后续预览方式</p>
          </div>
        </div>
        <el-form-item prop="processType" class="type-form-item">
          <div class="type-options">
            <button
              type="button"
              class="type-option"
              :class="{ 'is-active': processType === 'structured' }"
              @click="emit('update:processType', 'structured')"
            >
              <span class="type-icon"><i class="fa fa-table" /></span>
              <span>
                <strong>结构化数据</strong>
                <small>适用于 CSV、Excel、JSONL 等固定字段数据</small>
              </span>
              <i class="fa fa-check-circle selection-mark" />
            </button>
            <button
              type="button"
              class="type-option"
              :class="{ 'is-active': processType === 'unstructured' }"
              @click="emit('update:processType', 'unstructured')"
            >
              <span class="type-icon"><i class="fa fa-file-text-o" /></span>
              <span>
                <strong>非结构化数据</strong>
                <small>适用于文档、文本、问答等需要切分的数据</small>
              </span>
              <i class="fa fa-check-circle selection-mark" />
            </button>
            <button
              type="button"
              class="type-option"
              :class="{ 'is-active': processType === 'external' }"
              @click="emit('update:processType', 'external')"
            >
              <span class="type-icon"><i class="fa fa-cloud-download" /></span>
              <span>
                <strong>外来数据源拉取</strong>
                <small>适用于数据库、API 接口等需远程拉取的外部数据</small>
              </span>
              <i class="fa fa-check-circle selection-mark" />
            </button>
          </div>
        </el-form-item>
      </div>

      <template v-if="processType === 'structured'">
        <div class="form-section structured-options-section">
          <div class="section-title-row">
            <div>
              <h3>预处理选项</h3>
              <p>选择在生成问答对之前需要执行的数据处理方式</p>
            </div>
          </div>
          <el-checkbox-group
            :model-value="structuredOptions.preprocessOptions"
            class="preprocess-option-grid"
            @update:model-value="updatePreprocessOptions"
          >
            <el-checkbox
              v-for="option in PREPROCESS_OPTIONS"
              :key="option.value"
              :value="option.value"
              class="preprocess-option"
            >
              <span class="preprocess-option-copy">
                <strong>{{ option.label }}</strong>
                <small>{{ option.description }}</small>
              </span>
            </el-checkbox>
          </el-checkbox-group>
        </div>

        <div class="form-section generation-options-section">
          <div class="section-title-row">
            <div>
              <h3>生成选项</h3>
              <p>配置每条结构化记录生成问答对的方式和数量</p>
            </div>
          </div>
          <div class="generation-option-list">
            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>语义丰富表达</strong>
                <small>使用大模型将问答表述得更自然、柔和</small>
              </div>
              <el-switch
                :model-value="structuredOptions.semanticEnrichment"
                inline-prompt
                active-text="开"
                inactive-text="关"
                @update:model-value="updateSemanticEnrichment"
              />
            </div>
            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>每行生成数量</strong>
                <small>每行结构化数据生成的问答对数量</small>
              </div>
              <el-input-number
                :model-value="structuredOptions.qaPairsPerRow"
                :min="1"
                :max="5"
                :step="1"
                controls-position="right"
                @update:model-value="updateStructuredField('qaPairsPerRow', Number($event) || 1)"
              />
            </div>
            <div class="generation-option-row dataset-split-row">
              <div class="generation-option-copy">
                <strong>数据集划分</strong>
                <small>按比例将生成后的问答对随机划分为训练集、验证集和测试集</small>
              </div>
              <div class="dataset-split-config">
                <div class="dataset-split-grid">
                  <label class="dataset-split-field">
                    <span>训练集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="structuredOptions.datasetSplit.train"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="训练集比例"
                        @update:model-value="updateDatasetSplit('train', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                  <label class="dataset-split-field">
                    <span>验证集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="structuredOptions.datasetSplit.validation"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="验证集比例"
                        @update:model-value="updateDatasetSplit('validation', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                  <label class="dataset-split-field">
                    <span>测试集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="structuredOptions.datasetSplit.test"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="测试集比例"
                        @update:model-value="updateDatasetSplit('test', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                </div>
                <div class="dataset-split-summary" :class="{ 'is-invalid': splitTotal !== 100 }">
                  <span>总计 {{ splitTotal }}%</span>
                  <span v-if="splitTotal !== 100" role="alert">训练集、验证集和测试集比例总和必须为 100%</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>

      <template v-if="processType === 'unstructured'">
        <div class="form-section unstructured-options-section">
          <div class="section-title-row">
            <div>
              <h3>预处理选项</h3>
              <p>默认使用推荐策略，只需决定是否需要脱敏</p>
            </div>
          </div>
          <div class="generation-option-list compact-option-list">
            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>智能预处理</strong>
                <small>自动完成内容清理、结构解析、短段合并、质量过滤、去重及上下文保留</small>
              </div>
              <el-switch
                :model-value="smartPreprocessEnabled"
                aria-label="智能预处理"
                inline-prompt
                active-text="开"
                inactive-text="关"
                @update:model-value="updateSmartPreprocess"
              />
            </div>
            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>敏感信息脱敏</strong>
                <small>处理姓名、手机号、邮箱和证件号等信息</small>
              </div>
              <el-switch
                :model-value="desensitizeEnabled"
                aria-label="敏感信息脱敏"
                inline-prompt
                active-text="开"
                inactive-text="关"
                @update:model-value="updateDesensitize"
              />
            </div>
          </div>
        </div>

        <div class="form-section chunk-options-section">
          <div class="section-title-row">
            <div>
              <h3>切分选项</h3>
              <p>以语义完整为优先，将长文档拆成可独立生成问答的内容块</p>
            </div>
          </div>

          <div class="chunk-settings-grid is-basic">
            <label class="config-field">
              <span class="config-field-label">切分方式</span>
              <el-select
                :model-value="unstructuredOptions.chunkMethod"
                aria-label="切分方式"
                @update:model-value="updateUnstructuredField('chunkMethod', $event)"
              >
                <el-option
                  v-for="method in CHUNK_METHODS"
                  :key="method.value"
                  :label="method.label"
                  :value="method.value"
                />
              </el-select>
              <small>推荐使用自动语义切分，在长度限制内优先保留完整句段</small>
            </label>

            <label class="config-field">
              <span class="config-field-label">切片长度</span>
              <span class="unit-input">
                <el-input-number
                  :model-value="unstructuredOptions.chunkSize"
                  :min="200"
                  :max="2000"
                  :step="50"
                  :precision="0"
                  controls-position="right"
                  aria-label="切片长度"
                  @update:model-value="updateUnstructuredNumber('chunkSize', $event)"
                />
                <span>Token</span>
              </span>
              <small>单个切片的目标上限，默认 800 Token</small>
            </label>

            <label class="config-field">
              <span class="config-field-label">重叠长度</span>
              <span class="unit-input">
                <el-input-number
                  :model-value="unstructuredOptions.chunkOverlap"
                  :min="0"
                  :max="500"
                  :step="10"
                  :precision="0"
                  controls-position="right"
                  aria-label="重叠长度"
                  @update:model-value="updateUnstructuredNumber('chunkOverlap', $event)"
                />
                <span>Token</span>
              </span>
              <small>在相邻切片中最多重复保留的上下文，默认 100 Token</small>
            </label>
          </div>

          <p class="chunk-estimation-note">
            Token 数为轻量估算值，实际长度以训练使用的模型分词器为准。
          </p>

          <p v-if="chunkValidationMessage" class="option-validation-message" role="alert">
            {{ chunkValidationMessage }}
          </p>

          <button
            type="button"
            class="advanced-settings-toggle"
            :aria-expanded="advancedChunkSettingsOpen"
            aria-controls="unstructured-advanced-settings"
            @click="advancedChunkSettingsOpen = !advancedChunkSettingsOpen"
          >
            <span>
              <strong>高级设置</strong>
              <small>最小切片长度、自定义分隔符和特殊内容保护</small>
            </span>
            <i class="fa" :class="advancedChunkSettingsOpen ? 'fa-chevron-up' : 'fa-chevron-down'" />
          </button>

          <div
            v-if="advancedChunkSettingsOpen"
            id="unstructured-advanced-settings"
            class="advanced-settings-panel"
          >
            <div class="advanced-settings-grid">
              <label class="config-field">
                <span class="config-field-label">最小切片长度</span>
                <span class="unit-input">
                  <el-input-number
                    :model-value="unstructuredOptions.minChunkSize"
                    :min="20"
                    :max="500"
                    :step="10"
                    :precision="0"
                    controls-position="right"
                    aria-label="最小切片长度"
                    @update:model-value="updateUnstructuredNumber('minChunkSize', $event)"
                  />
                  <span>Token</span>
                </span>
                <small>过短的尾部内容会尽量并入前一个切片</small>
              </label>

              <label v-if="unstructuredOptions.chunkMethod === 'custom'" class="config-field">
                <span class="config-field-label">自定义分隔符</span>
                <el-input
                  :model-value="unstructuredOptions.customDelimiter"
                  maxlength="40"
                  show-word-limit
                  placeholder="例如：--- 或 ###"
                  aria-label="自定义分隔符"
                  @update:model-value="updateUnstructuredField('customDelimiter', $event)"
                />
                <small>系统会优先在分隔符位置结束当前切片</small>
              </label>
            </div>

            <div class="generation-option-row advanced-protection-row">
              <div class="generation-option-copy">
                <strong>保护表格、代码和列表</strong>
                <small>避免切分点破坏特殊内容块的完整性</small>
              </div>
              <el-switch
                :model-value="preserveSpecialContentEnabled"
                aria-label="保护表格、代码和列表"
                inline-prompt
                active-text="开"
                inactive-text="关"
                @update:model-value="updateSpecialContentProtection"
              />
            </div>
          </div>
        </div>

        <div class="form-section generation-options-section">
          <div class="section-title-row">
            <div>
              <h3>生成选项</h3>
              <p>只保留会直接影响输出的核心设置</p>
            </div>
          </div>
          <div class="generation-option-list">
            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>语义丰富表达</strong>
                <small>使用大模型将问答表述得更自然、柔和</small>
              </div>
              <el-switch
                :model-value="unstructuredOptions.semanticEnrichment"
                aria-label="非结构化语义丰富表达"
                inline-prompt
                active-text="开"
                inactive-text="关"
                @update:model-value="updateUnstructuredField('semanticEnrichment', Boolean($event))"
              />
            </div>

            <div class="generation-option-row">
              <div class="generation-option-copy">
                <strong>每个切片生成数量</strong>
                <small>每个内容切片最多生成 3 个不同角度的问答对</small>
              </div>
              <el-input-number
                :model-value="unstructuredOptions.qaPairsPerChunk"
                :min="1"
                :max="3"
                :step="1"
                :precision="0"
                controls-position="right"
                aria-label="每个切片生成数量"
                @update:model-value="updateUnstructuredNumber('qaPairsPerChunk', $event)"
              />
            </div>

            <div class="generation-option-row dataset-split-row">
              <div class="generation-option-copy">
                <strong>数据集划分</strong>
                <small>按比例将生成后的问答对随机划分为训练集、验证集和测试集</small>
              </div>
              <div class="dataset-split-config">
                <div class="dataset-split-grid">
                  <label class="dataset-split-field">
                    <span>训练集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="unstructuredOptions.datasetSplit.train"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="非结构化训练集比例"
                        @update:model-value="updateUnstructuredDatasetSplit('train', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                  <label class="dataset-split-field">
                    <span>验证集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="unstructuredOptions.datasetSplit.validation"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="非结构化验证集比例"
                        @update:model-value="updateUnstructuredDatasetSplit('validation', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                  <label class="dataset-split-field">
                    <span>测试集</span>
                    <span class="dataset-split-input">
                      <el-input-number
                        :model-value="unstructuredOptions.datasetSplit.test"
                        :min="0"
                        :max="100"
                        :step="1"
                        :precision="0"
                        controls-position="right"
                        aria-label="非结构化测试集比例"
                        @update:model-value="updateUnstructuredDatasetSplit('test', $event)"
                      />
                      <span>%</span>
                    </span>
                  </label>
                </div>
                <div class="dataset-split-summary" :class="{ 'is-invalid': unstructuredSplitTotal !== 100 }">
                  <span>总计 {{ unstructuredSplitTotal }}%</span>
                  <span v-if="unstructuredSplitTotal !== 100" role="alert">
                    训练集、验证集和测试集比例总和必须为 100%
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>

    </el-form>
  </section>
</template>

<style scoped lang="scss">
.task-setup-step {
  width: 100%;
}


.form-section {
  padding: 0 0 26px;
  margin-bottom: 26px;
  border-bottom: 1px solid #edf0f5;

  &:last-child {
    margin-bottom: 0;
    border-bottom: 0;
  }

  h3 {
    margin: 0 0 16px;
    color: #2f3747;
    font-size: 15px;
    font-weight: 650;
  }
}

.basic-grid {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.preprocess-option-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

.preprocess-option {
  width: 100%;
  min-height: 64px;
  margin-right: 0;
  padding: 12px 14px;
  box-sizing: border-box;
  align-items: flex-start;
  border: 1px solid #e2e5ec;
  border-radius: 8px;
  transition: border-color 0.18s ease, background-color 0.18s ease;

  &:hover {
    border-color: #b7b2f7;
  }

  &.is-checked {
    background: #fafaff;
    border-color: #8b82f4;
  }

  :deep(.el-checkbox__input) {
    margin-top: 3px;
  }

  :deep(.el-checkbox__label) {
    min-width: 0;
    padding-left: 10px;
    white-space: normal;
  }
}

.preprocess-option-copy,
.generation-option-copy {
  display: grid;
  gap: 4px;

  strong {
    color: #344054;
    font-size: 13px;
    font-weight: 600;
  }

  small {
    color: #8a93a3;
    font-size: 12px;
    line-height: 1.5;
  }
}

.generation-option-list {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}

.compact-option-list {
  gap: 8px;

  .generation-option-row {
    min-height: 58px;
  }
}

.chunk-settings-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-top: 16px;
}

.config-field {
  display: grid;
  align-content: start;
  gap: 8px;
  min-width: 0;
  padding: 14px;
  color: #344054;
  background: #fbfcfe;
  border: 1px solid #e2e5ec;
  border-radius: 8px;

  > small {
    color: #8a93a3;
    font-size: 12px;
    line-height: 1.5;
  }

  :deep(.el-select),
  :deep(.el-input) {
    width: 100%;
  }
}

.config-field-label {
  font-size: 13px;
  font-weight: 600;
}

.unit-input {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #7b8495;
  font-size: 12px;

  :deep(.el-input-number) {
    width: 100%;
  }
}

.option-validation-message {
  display: block;
  margin: 8px 0 0;
  color: #dc2626;
  font-size: 12px;
  line-height: 1.5;
}

.chunk-estimation-note {
  margin: 9px 0 0;
  color: #8a93a3;
  font-size: 12px;
  line-height: 1.5;
}

.advanced-settings-toggle {
  display: flex;
  width: 100%;
  min-height: 48px;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 12px;
  padding: 10px 14px;
  color: #344054;
  text-align: left;
  background: #fbfcfe;
  border: 1px solid #e2e5ec;
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease;

  &:hover {
    background: #f8f7ff;
    border-color: #b7b2f7;
  }

  &:focus-visible {
    outline: 2px solid #5b50f2;
    outline-offset: 2px;
  }

  > span {
    display: grid;
    gap: 3px;
  }

  strong {
    font-size: 13px;
    font-weight: 600;
  }

  small {
    color: #8a93a3;
    font-size: 12px;
    line-height: 1.5;
  }

  i {
    flex: 0 0 auto;
    color: #7b8495;
    font-size: 12px;
  }
}

.advanced-settings-panel {
  display: grid;
  gap: 12px;
  margin-top: 8px;
  padding: 12px;
  background: #fbfcfe;
  border: 1px solid #e2e5ec;
  border-radius: 8px;

  .config-field,
  .advanced-protection-row {
    background: #fff;
  }
}

.advanced-settings-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.generation-option-row {
  display: flex;
  min-height: 64px;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 12px 14px;
  box-sizing: border-box;
  border: 1px solid #e2e5ec;
  border-radius: 8px;
}

.dataset-split-row {
  align-items: stretch;
  flex-direction: column;
}

.dataset-split-config {
  display: grid;
  gap: 10px;
}

.dataset-split-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.dataset-split-field {
  display: grid;
  gap: 7px;
  color: #5f6878;
  font-size: 12px;
}

.dataset-split-input {
  display: flex;
  align-items: center;
  gap: 8px;

  :deep(.el-input-number) {
    width: 100%;
  }
}

.dataset-split-summary {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: #2ca66a;
  font-size: 12px;

  &.is-invalid {
    color: #dc2626;
  }
}

.section-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;

  h3 {
    margin-bottom: 5px;
  }

  p {
    margin: 0;
    color: #8a93a3;
    font-size: 12px;
  }
}

.type-form-item {
  margin-top: 16px;
}

.type-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  width: 100%;
}

.type-option {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 96px;
  padding: 18px;
  color: #4b5563;
  text-align: left;
  background: #fff;
  border: 1px solid #dfe3ea;
  border-radius: 9px;
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease;

  &:hover {
    border-color: #a8a3ff;
  }

  &.is-active {
    background: #fafaff;
    border-color: #5b50f2;
    box-shadow: 0 0 0 1px rgba(91, 80, 242, 0.08);
  }

  strong,
  small {
    display: block;
  }

  strong {
    margin-bottom: 6px;
    color: #262d3d;
    font-size: 14px;
  }

  small {
    color: #7b8495;
    font-size: 12px;
    line-height: 1.6;
  }
}

.type-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  color: #5b50f2;
  font-size: 18px;
  background: #f0efff;
  border-radius: 9px;
}

.selection-mark {
  position: absolute;
  top: 12px;
  right: 12px;
  color: #5b50f2;
  opacity: 0;
}

.type-option.is-active .selection-mark {
  opacity: 1;
}

@media (max-width: 900px) {
  .type-options {
    grid-template-columns: minmax(0, 1fr);
  }

  .preprocess-option-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .chunk-settings-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .advanced-settings-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .dataset-split-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .dataset-split-summary {
    align-items: flex-start;
    flex-direction: column;
  }

  .generation-option-row:not(.dataset-split-row) {
    align-items: flex-start;
    flex-direction: column;
  }

  .compact-option-list .generation-option-row,
  .advanced-protection-row {
    align-items: center;
    flex-direction: row;
  }

}
</style>
