<script setup lang="ts">
/**
 * TextProps —— 文本控件属性（§5.2/§5.3）：内容（静态/绑定/表达式）+ 排版样式
 */
import { computed } from 'vue'
import {
  NInput,
  NInputNumber,
  NSelect,
  NColorPicker,
  NRadioGroup,
  NRadioButton,
  NButton,
} from 'naive-ui'
import type { CellFormat, CellFormatKind, TextControl, TextStyle } from '@/types/control'
import { useDesignerStore } from '@/design/stores/designer'
import { useDataSourceStore } from '@/design/stores/dataSource'
import { FONT_CATALOG } from '@/core/fonts/catalog'
import BindingEditor from './BindingEditor.vue'
import {
  formatKindOptions,
  datePatternOptions,
  currencyCodeOptions,
  makeFormat,
  needsPattern,
  needsDigits,
  needsCode,
  supportsThousands,
  suggestKindByFieldType,
} from '@/design/format-options'

const store = useDesignerStore()
const control = computed(() => store.selectedControl as TextControl | null)
const ds = useDataSourceStore()

/** 内置字体下拉选项（空值 = 系统默认） */
const fontOptions = [
  { label: '系统默认', value: '' },
  ...FONT_CATALOG.map((f) => ({ label: f.label, value: f.family })),
]

function patch(p: Record<string, unknown>): void {
  if (control.value) store.updateControl(control.value.id, p)
}

function patchStyle(p: Partial<TextStyle>): void {
  if (!control.value) return
  patch({ style: { ...control.value.style, ...p } })
}

/** B / I / U 三键：加粗 / 斜体 / 下划线（切换式） */
const isBold = computed(() => (control.value?.style?.fontWeight ?? 'normal') === 'bold')
const isItalic = computed(() => (control.value?.style?.fontStyle ?? 'normal') === 'italic')
const isUnderline = computed(() => (control.value?.style?.textDecoration ?? 'none') === 'underline')
function toggleBold(): void {
  patchStyle({ fontWeight: isBold.value ? 'normal' : 'bold' })
}
function toggleItalic(): void {
  patchStyle({ fontStyle: isItalic.value ? 'normal' : 'italic' })
}
function toggleUnderline(): void {
  patchStyle({ textDecoration: isUnderline.value ? 'none' : 'underline' })
}

/** 内容模式：静态文本 / 字段绑定 / 表达式（三选一） */
const contentMode = computed({
  get: () =>
    control.value?.expression ? 'expression' : control.value?.binding ? 'binding' : 'static',
  set: (mode: string) => {
    if (!control.value) return
    if (mode === 'static') patch({ binding: undefined, expression: undefined })
    else if (mode === 'binding')
      patch({ binding: control.value.binding ?? 'order.orderNo', expression: undefined })
    else patch({ expression: control.value.expression ?? '{{order.total}}', binding: undefined })
  },
})

/* -------------------------------- 数据格式 -------------------------------- */
/* 仅绑定模式生效：expression 模式请用 {{field | date:'...'}} 过滤器，不在此重复设置。 */

const textFormat = computed<CellFormat>(() => control.value?.format ?? { kind: 'none' })

/** 绑定字段在数据源里的类型（用于提示选哪种格式） */
const boundFieldType = computed(() => {
  const path = control.value?.binding
  if (!path) return undefined
  const f = ds.flatFields.find((x) => x.path === path)
  return f?.type
})
const formatHint = computed(() => {
  const k = suggestKindByFieldType(boundFieldType.value)
  if (k === 'date') return '绑定的字段为「日期」类型，建议选择日期格式。'
  if (k === 'decimal') return '绑定的字段为「数值」类型，建议选择整数 / 小数 / 货币格式。'
  return ''
})

function patchFormat(fmt: CellFormat): void {
  patch({ format: fmt.kind === 'none' ? undefined : fmt })
}
function setFormatKind(kind: CellFormatKind): void {
  if (kind === 'none') {
    patch({ format: undefined })
    return
  }
  // 第一次选择某类型：套用该类型默认格式，避免半成品
  const cur = control.value?.format
  patchFormat(cur && cur.kind === kind ? cur : makeFormat(kind))
}
function isPresetDatePattern(p?: string): boolean {
  return Boolean(p && datePatternOptions.some((o) => o.value !== '__custom__' && o.value === p))
}
</script>

<template>
  <div v-if="control" class="props-section">
    <div class="props-title">内容设置</div>

    <div class="props-row">
      <span class="props-label">类型</span>
      <NRadioGroup v-model:value="contentMode" size="small">
        <NRadioButton value="static">静态</NRadioButton>
        <NRadioButton value="binding">绑定</NRadioButton>
        <NRadioButton value="expression">表达式</NRadioButton>
      </NRadioGroup>
    </div>

    <div v-if="contentMode === 'static'" class="props-row">
      <NInput
        type="textarea"
        size="small"
        :autosize="{ minRows: 3, maxRows: 4 }"
        :value="control.value ?? ''"
        placeholder="文本内容"
        @update:value="patch({ value: $event })"
      />
    </div>
    <div v-else-if="contentMode === 'binding'" class="props-row">
      <BindingEditor :value="control.binding" @update:value="patch({ binding: $event })" />
    </div>
    <div v-if="contentMode === 'binding'" class="props-section">
      <div class="props-title">数据格式</div>

      <div v-if="formatHint" class="props-tip">{{ formatHint }}</div>

      <div class="props-row">
        <span class="props-label">类型</span>
        <NSelect
          size="small"
          :value="textFormat.kind"
          :options="formatKindOptions"
          @update:value="setFormatKind"
        />
      </div>

      <div v-if="needsPattern(textFormat.kind)" class="props-row">
        <span class="props-label">日期模板</span>
        <NSelect
          size="small"
          :value="isPresetDatePattern(textFormat.pattern) ? textFormat.pattern : '__custom__'"
          :options="datePatternOptions"
          @update:value="
            (v: string) => {
              if (v !== '__custom__') patchFormat({ ...textFormat, kind: 'date', pattern: v })
            }
          "
        />
      </div>
      <div v-if="needsPattern(textFormat.kind) && !isPresetDatePattern(textFormat.pattern)" class="props-row">
        <span class="props-label">自定义</span>
        <NInput
          size="small"
          :value="textFormat.pattern ?? 'YYYY-MM-DD'"
          placeholder="YYYY-MM-DD HH:mm"
          @update:value="(v: string) => patchFormat({ ...textFormat, kind: 'date', pattern: v || 'YYYY-MM-DD' })"
        />
      </div>

      <div v-if="needsDigits(textFormat.kind)" class="props-row">
        <span class="props-label">小数位</span>
        <NInputNumber
          size="small"
          button-placement="both"
          :value="textFormat.digits ?? 2"
          :min="0"
          :max="6"
          :precision="0"
          @update:value="(v: number | null) => patchFormat({ ...textFormat, digits: v ?? 0 })"
        />
      </div>

      <div v-if="needsCode(textFormat.kind)" class="props-row">
        <span class="props-label">币种</span>
        <NSelect
          size="small"
          :value="textFormat.code ?? 'CNY'"
          :options="currencyCodeOptions"
          @update:value="(v: string) => patchFormat({ ...textFormat, kind: 'currency', code: v })"
        />
      </div>

      <div v-if="supportsThousands(textFormat.kind)" class="props-row">
        <span class="props-label">千分位</span>
        <NRadioGroup
          size="small"
          :value="textFormat.thousands === false ? 'off' : 'on'"
          @update:value="(v: string) => patchFormat({ ...textFormat, thousands: v === 'on' })"
        >
          <NRadioButton value="on">开</NRadioButton>
          <NRadioButton value="off">关</NRadioButton>
        </NRadioGroup>
      </div>

      <NButton size="tiny" quaternary @click="patch({ format: undefined })">清除格式</NButton>
    </div>
    <div v-else class="props-row">
      <NInput
        size="small"
        :value="control.expression ?? ''"
        placeholder="{{order.total | currency:'CNY'}}"
        @update:value="patch({ expression: $event || undefined })"
      />
    </div>
  </div>

  <div v-if="control" class="props-section">
    <div class="props-title">排版设置</div>

    <div class="grid grid-cols-2 gap-2">
      <div class="props-row">
        <span class="props-label">字号</span>
        <NInputNumber
          size="small"
          button-placement="both"
          :value="control.style?.fontSize ?? 12"
          :min="6"
          :max="72"
          :precision="1"
          @update:value="patchStyle({ fontSize: $event ?? 12 })"
        />
      </div>
      <div class="props-row">
        <span class="props-label">行高</span>
        <NInputNumber
          size="small"
          button-placement="both"
          :value="control.style?.lineHeight ?? 1.16"
          :min="0.8"
          :max="4"
          :step="0.05"
          :precision="2"
          @update:value="patchStyle({ lineHeight: $event ?? 1.16 })"
        />
      </div>
    </div>

    <div class="props-row">
      <span class="props-label">样式</span>
      <div class="flex items-center gap-1">
        <NButton size="small" :type="isBold ? 'primary' : 'default'" title="加粗" @click="toggleBold"><b>B</b></NButton>
        <NButton size="small" :type="isItalic ? 'primary' : 'default'" title="斜体" @click="toggleItalic"><i>I</i></NButton>
        <NButton size="small" :type="isUnderline ? 'primary' : 'default'" title="下划线" @click="toggleUnderline"><u>U</u></NButton>
      </div>
    </div>

    <div class="props-row">
      <span class="props-label">对齐</span>
      <NRadioGroup
        size="small"
        :value="control.style?.textAlign ?? 'left'"
        @update:value="patchStyle({ textAlign: $event })"
      >
        <NRadioButton value="left">左</NRadioButton>
        <NRadioButton value="center">中</NRadioButton>
        <NRadioButton value="right">右</NRadioButton>
      </NRadioGroup>
    </div>

    <div class="props-row">
      <span class="props-label">字体</span>
      <NSelect
        size="small"
        :value="control.style?.fontFamily ?? ''"
        :options="fontOptions"
        placeholder="系统默认"
        @update:value="patchStyle({ fontFamily: $event || undefined })"
      />
    </div>

    <div class="props-row">
      <span class="props-label">颜色</span>
      <NColorPicker
        size="small"
        :modes="['hex']"
        :value="control.style?.fill ?? '#000000'"
        :swatches="['#000000', '#333333', '#666666', '#999999', '#1677FF', '#F5222D']"
        @update:value="patchStyle({ fill: $event })"
      />
    </div>

    <div class="props-row">
      <span class="props-label">字距</span>
      <NInputNumber
        size="small"
        button-placement="both"
        :value="control.style?.letterSpacing ?? 0"
        :step="0.5"
        :precision="1"
        @update:value="patchStyle({ letterSpacing: $event ?? 0 })"
      />
    </div>
  </div>
</template>
