<template>
  <div
    class="inline-field-configurator"
    tabindex="-1"
    role="dialog"
    aria-label="内联编辑字段"
    @keydown.esc="onCancel"
  >
    <div class="inline-field-configurator__header">
      <FieldTypeIcon :type="localType" />
      <span class="inline-field-configurator__title">编辑字段</span>
      <a-button
        type="text"
        size="small"
        :icon="h(CloseOutlined)"
        aria-label="关闭"
        @click="onCancel"
      />
    </div>

    <a-form layout="vertical" size="small">
      <a-form-item label="字段名称">
        <a-input
          ref="nameInputRef"
          v-model:value="localName"
          :maxlength="100"
          placeholder="字段名称"
        />
      </a-form-item>

      <a-form-item label="字段类型">
        <a-select v-model:value="localType" @change="onTypeChange">
          <a-select-option value="text">文本</a-select-option>
          <a-select-option value="number">数字</a-select-option>
          <a-select-option value="date">日期</a-select-option>
          <a-select-option value="select">单选</a-select-option>
          <a-select-option value="multiselect">多选</a-select-option>
          <a-select-option value="formula">公式</a-select-option>
          <a-select-option value="attachment">附件</a-select-option>
          <a-select-option value="image">图片</a-select-option>
        </a-select>
      </a-form-item>

      <!-- Select / Multiselect: options editor -->
      <template v-if="localType === 'select' || localType === 'multiselect'">
        <a-form-item label="选项列表">
          <div
            v-for="(_, idx) in selectOptions"
            :key="idx"
            class="inline-field-configurator__option-row"
          >
            <a-input
              v-model:value="selectOptions[idx]"
              placeholder="选项值"
              :maxlength="200"
            />
            <a-button
              type="text"
              danger
              size="small"
              :icon="h(DeleteOutlined)"
              aria-label="删除选项"
              @click="removeOption(idx)"
            />
          </div>
          <a-button
            type="dashed"
            block
            size="small"
            :icon="h(PlusOutlined)"
            @click="addOption"
          >
            添加选项
          </a-button>
        </a-form-item>
      </template>

      <!-- Formula: expression editor with live validation -->
      <template v-if="localType === 'formula'">
        <a-form-item label="公式表达式">
          <a-textarea
            v-model:value="formulaExpr"
            placeholder="例如: {field_id_1} + {field_id_2} 或 SUM({field_id})"
            :rows="3"
            :maxlength="2000"
          />
          <div class="inline-field-configurator__formula-hint">
            用 {字段ID} 引用其他字段，支持 SUM/AVG/COUNT/MIN/MAX/ABS/ROUND/IF/LEN/CONCAT
          </div>
        </a-form-item>

        <a-form-item v-if="formulaExpr" label="语法校验">
          <a-alert
            v-if="formulaValid === true"
            type="success"
            message="公式语法正确"
            show-icon
          />
          <a-alert
            v-else-if="formulaValid === false"
            type="error"
            :message="formulaError || '公式语法错误'"
            show-icon
          />
          <a-alert v-else type="info" message="校验中..." show-icon />
        </a-form-item>
      </template>

      <!-- Date: format -->
      <template v-if="localType === 'date'">
        <a-form-item label="日期格式">
          <a-select v-model:value="dateFormat">
            <a-select-option value="YYYY-MM-DD">YYYY-MM-DD</a-select-option>
            <a-select-option value="YYYY-MM-DD HH:mm">YYYY-MM-DD HH:mm</a-select-option>
            <a-select-option value="YYYY/MM/DD">YYYY/MM/DD</a-select-option>
          </a-select>
        </a-form-item>
      </template>
    </a-form>

    <!-- Type-change compatibility warning (blocks submit) -->
    <a-alert
      v-if="compatWarning"
      class="inline-field-configurator__warning"
      type="warning"
      show-icon
      message="无法转换字段类型"
      :description="compatWarning"
    />

    <!-- Submit error with retry -->
    <ErrorState
      v-if="submitError"
      class="inline-field-configurator__error"
      message="保存失败"
      :description="submitError"
      :retryable="true"
      :retrying="submitting"
      @retry="onSubmit"
    />

    <div class="inline-field-configurator__actions">
      <a-button size="small" :disabled="submitting" @click="onCancel">
        取消
      </a-button>
      <a-button
        type="primary"
        size="small"
        :loading="submitting"
        :disabled="!canSubmit"
        @click="onSubmit"
      >
        保存
      </a-button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, h } from 'vue'
import {
  Button as AButton,
  Input as AInput,
  Select as ASelect,
  Alert as AAlert,
} from 'ant-design-vue'
import {
  CloseOutlined,
  DeleteOutlined,
  PlusOutlined,
} from '@ant-design/icons-vue'
import type { IBitableField, FieldType } from '@/api/bitable'
import { useBitableStore } from '@/stores/bitable'
import { checkTypeCompatibility } from '@/helpers/fieldRenderUtils'
import FieldTypeIcon from './FieldTypeIcon.vue'
import ErrorState from './ErrorState.vue'

const props = defineProps<{
  field: IBitableField
  // ponytail: tableId is reserved for future table-scoped operations; the
  // PATCH /fields/{id} endpoint only needs fieldId. Kept per U2 spec contract.
  tableId?: string
}>()

const emit = defineEmits<{
  (e: 'saved', field: IBitableField): void
  (e: 'cancel'): void
}>()

const store = useBitableStore()

const localName = ref(props.field.name)
const localType = ref<FieldType>(props.field.field_type)
const selectOptions = ref<string[]>(
  (props.field.config?.options as string[]) ?? [],
)
const formulaExpr = ref((props.field.config?.formula_expr as string) ?? '')
const dateFormat = ref((props.field.config?.format as string) ?? 'YYYY-MM-DD')

// Formula validation state (debounced API check, same as FieldConfigForm)
const formulaValid = ref<boolean | null>(null)
const formulaError = ref<string | null>(null)
let validateTimer: ReturnType<typeof setTimeout> | null = null

const submitting = ref(false)
const submitError = ref<string | null>(null)
const nameInputRef = ref<InstanceType<typeof AInput> | null>(null)

// Existing values for the field across all loaded records (for compat check)
const existingValues = computed<unknown[]>(() =>
  store.records.map((r) => r.values[props.field.id]),
)

// Compatibility result when type changes
const compat = computed(() =>
  checkTypeCompatibility(
    props.field.field_type,
    localType.value,
    existingValues.value,
  ),
)

const compatWarning = computed<string | null>(() =>
  compat.value.compatible ? null : (compat.value.reason ?? '当前数据不支持该类型转换'),
)

// Debounced formula validation
watch(formulaExpr, (val) => {
  if (!val.trim()) {
    formulaValid.value = null
    return
  }
  formulaValid.value = null
  if (validateTimer) clearTimeout(validateTimer)
  validateTimer = setTimeout(async () => {
    try {
      const { bitableApi } = await import('@/api/bitable')
      const result = await bitableApi.validateFormula(val)
      formulaValid.value = result.valid
      formulaError.value = result.error ?? null
    } catch (err) {
      formulaValid.value = false
      formulaError.value = err instanceof Error ? err.message : String(err)
    }
  }, 500)
})

function onTypeChange(): void {
  // Reset type-specific config when type changes (mirrors FieldConfigForm)
  selectOptions.value = []
  formulaExpr.value = ''
  formulaValid.value = null
}

function addOption(): void {
  selectOptions.value.push('')
}

function removeOption(idx: number): void {
  selectOptions.value.splice(idx, 1)
}

function buildConfig(): Record<string, unknown> {
  const config: Record<string, unknown> = {}
  if (localType.value === 'select' || localType.value === 'multiselect') {
    config.options = selectOptions.value.filter((o) => o.trim())
  }
  if (localType.value === 'formula') {
    config.formula_expr = formulaExpr.value
  }
  if (localType.value === 'date') {
    config.format = dateFormat.value
  }
  return config
}

const isFormulaStateValid = computed(() => {
  if (localType.value !== 'formula') return true
  if (!formulaExpr.value.trim()) return false
  return formulaValid.value === true
})

const canSubmit = computed(() => {
  if (submitting.value) return false
  if (!localName.value.trim()) return false
  if (!compat.value.compatible) return false
  return isFormulaStateValid.value
})

function onCancel(): void {
  if (submitting.value) return
  submitError.value = null
  emit('cancel')
}

async function onSubmit(): Promise<void> {
  if (!canSubmit.value) return
  submitError.value = null
  submitting.value = true
  try {
    const patch: {
      name: string
      field_type?: FieldType
      config: Record<string, unknown>
    } = {
      name: localName.value.trim(),
      config: buildConfig(),
    }
    // Only send field_type when it actually changes (avoid no-op PATCH semantics)
    if (localType.value !== props.field.field_type) {
      patch.field_type = localType.value
    }
    const updated = await store.updateField(props.field.id, patch)
    if (!updated) {
      // store.updateField surfaces errors via notification; show inline retry too
      submitError.value = '服务器返回空响应，请重试'
      return
    }
    emit('saved', updated)
  } catch (err) {
    submitError.value = err instanceof Error ? err.message : String(err)
  } finally {
    submitting.value = false
  }
}

onMounted(() => {
  // Move focus to the first field for keyboard accessibility (U2 scenario 5).
  // a-input exposes focus() at runtime; cast to a minimal structural type
  // because InstanceType<typeof AInput> doesn't surface the imperative method.
  const inputEl = nameInputRef.value as { focus?: () => void } | null
  inputEl?.focus?.()
})
</script>

<style scoped>
.inline-field-configurator {
  display: flex;
  flex-direction: column;
  gap: var(--bitable-spacing-sm);
  padding: var(--bitable-spacing-sm) 0;
  outline: none;
}

.inline-field-configurator__header {
  display: flex;
  align-items: center;
  gap: var(--bitable-spacing-xs);
  padding-bottom: var(--bitable-spacing-xs);
  border-bottom: 1px solid var(--bitable-color-border-split);
}

.inline-field-configurator__title {
  flex: 1;
  font-weight: 600;
  font-size: var(--bitable-font-md);
  color: var(--bitable-color-text);
}

.inline-field-configurator__option-row {
  display: flex;
  gap: var(--bitable-spacing-xs);
  margin-bottom: var(--bitable-spacing-xs);
}

.inline-field-configurator__formula-hint {
  margin-top: var(--bitable-spacing-xs);
  font-size: var(--bitable-font-xs);
  color: var(--bitable-color-text-tertiary);
}

.inline-field-configurator__warning {
  margin-top: var(--bitable-spacing-xs);
  border-radius: var(--bitable-radius-md);
}

.inline-field-configurator__error {
  margin-top: var(--bitable-spacing-xs);
  border-radius: var(--bitable-radius-md);
}

.inline-field-configurator__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--bitable-spacing-xs);
  margin-top: var(--bitable-spacing-xs);
}
</style>
