<script lang="ts" setup>
import type { SpreadsheetConfigJson } from '../config/spreadsheetDefaults';

import { computed, ref } from 'vue';

import {
  Button,
  Checkbox,
  Input,
  InputNumber,
  Popover,
  Select,
  Space,
  Switch,
  Table,
  Tabs,
} from 'ant-design-vue';

import ColorPicker from '#/components/form/components/color-picker.vue';
import type {
  CellType,
  ColumnConditionalFormat,
  ConditionalColorMode,
} from '#/components/canvas-spreadsheet';

import SpreadsheetFormulaField from './SpreadsheetFormulaField.vue';

const props = defineProps<{
  config: SpreadsheetConfigJson;
  disabled?: boolean;
}>();

const emit = defineEmits<{
  'update:config': [value: SpreadsheetConfigJson];
}>();

const formSubTab = ref('global');

const cellTypeOptions = [
  { label: '只读', value: 'readonly' },
  { label: '文本', value: 'text' },
  { label: '数字', value: 'number' },
  { label: '公式', value: 'formula' },
];

const textAlignOptions = [
  { label: '靠左', value: 'left' },
  { label: '居中', value: 'center' },
  { label: '靠右', value: 'right' },
];

const columnTextAlignOptions = [
  { label: '跟随全局', value: 'inherit' },
  ...textAlignOptions,
];

const rowHeightMode = computed({
  get() {
    return props.config.rowHeight === 'auto' ? 'auto' : 'fixed';
  },
  set(mode: 'auto' | 'fixed') {
    patchConfig({
      rowHeight: mode === 'auto' ? 'auto' : 32,
    });
  },
});

const rowHeightFixed = computed({
  get() {
    return typeof props.config.rowHeight === 'number'
      ? props.config.rowHeight
      : 32;
  },
  set(v: number) {
    patchConfig({ rowHeight: v || 32 });
  },
});

function patchConfig(partial: Partial<SpreadsheetConfigJson>) {
  emit('update:config', { ...props.config, ...partial });
}

function patchHeaders(headers: SpreadsheetConfigJson['headers']) {
  patchConfig({ headers: [...headers] });
}

function patchColumns(columns: SpreadsheetConfigJson['columns']) {
  patchConfig({ columns: [...columns] });
}

function nextColIndex() {
  const cols = [
    ...props.config.headers.map((h) => h.col),
    ...props.config.columns.map((c) => c.col),
  ];
  return cols.length > 0 ? Math.max(...cols) + 1 : 0;
}

function addHeader() {
  const col = nextColIndex();
  patchHeaders([
    ...props.config.headers,
    {
      title: `列${col + 1}`,
      col,
      fieldId: `field_${col}`,
      filterable: true,
    },
  ]);
}

function removeHeader(index: number) {
  const header = props.config.headers[index];
  if (!header) return;
  patchHeaders(props.config.headers.filter((_, i) => i !== index));
  patchColumns(
    props.config.columns.filter((c) => c.col !== header.col),
  );
}

function updateHeader(
  index: number,
  key: keyof SpreadsheetConfigJson['headers'][number],
  value: unknown,
) {
  const headers = props.config.headers.map((h, i) =>
    i === index ? { ...h, [key]: value } : h,
  );
  patchHeaders(headers);
}

function addColumn() {
  const col = nextColIndex();
  const fieldId = `field_${col}`;
  const fieldName = `列${col + 1}`;
  const headers = [...props.config.headers];
  if (!headers.some((h) => h.col === col)) {
    headers.push({
      title: fieldName,
      col,
      fieldId,
      filterable: true,
    });
  }
  patchConfig({
    headers,
    columns: [
      ...props.config.columns,
      {
        col,
        fieldId,
        fieldName,
        cellType: 'readonly' as CellType,
        editable: false,
      },
    ],
  });
}

function removeColumn(index: number) {
  const column = props.config.columns[index];
  if (!column) return;
  patchColumns(props.config.columns.filter((_, i) => i !== index));
  patchHeaders(props.config.headers.filter((h) => h.col !== column.col));
}

function updateColumn(
  index: number,
  key: keyof SpreadsheetConfigJson['columns'][number],
  value: unknown,
) {
  const columns = props.config.columns.map((c, i) => {
    if (i !== index) return c;
    const next = { ...c, [key]: value };
    if (key === 'cellType') {
      const cellType = value as CellType;
      if (cellType === 'formula' || cellType === 'readonly') {
        next.editable = false;
      }
    }
    return next;
  });

  let headers = props.config.headers;
  const column = columns[index];
  if (column && key === 'fieldName' && value) {
    const headerIdx = headers.findIndex((h) => h.col === column.col);
    if (headerIdx >= 0) {
      headers = headers.map((h, hi) =>
        hi === headerIdx ? { ...h, title: String(value) } : h,
      );
    } else {
      headers = [
        ...headers,
        {
          title: String(value),
          col: column.col,
          fieldId: column.fieldId,
          filterable: false,
        },
      ];
    }
  }

  if (column && key === 'cellType' && value === 'formula') {
    if (!headers.some((h) => h.col === column.col)) {
      headers = [
        ...headers,
        {
          title: column.fieldName || column.fieldId,
          col: column.col,
          fieldId: column.fieldId,
          filterable: false,
        },
      ];
    }
  }

  patchConfig({ headers, columns });
}

function updateColumnConditional(
  index: number,
  ruleKey: 'gt' | 'lt',
  field: 'threshold' | 'bgColor' | 'textColor' | 'colorMode',
  value: unknown,
) {
  const columns = props.config.columns.map((c, i) => {
    if (i !== index) return c;
    const cf: ColumnConditionalFormat = { ...(c.conditionalFormat ?? {}) };
    const prev = cf[ruleKey] ?? { threshold: 0, bgColor: '' };
    cf[ruleKey] = {
      ...prev,
      [field]: value,
    };
    return { ...c, conditionalFormat: cf };
  });
  patchColumns(columns);
}

const colorModeOptions = [
  { label: '背景', value: 'background' },
  { label: '文字', value: 'text' },
  { label: '两者', value: 'both' },
];

function conditionalColorMode(
  record: { conditionalFormat?: ColumnConditionalFormat },
  ruleKey: 'gt' | 'lt',
): ConditionalColorMode {
  return record.conditionalFormat?.[ruleKey]?.colorMode ?? 'background';
}

function showConditionalFields(record: { cellType?: string }) {
  return record.cellType === 'formula' || record.cellType === 'number';
}
</script>

<template>
  <div class="spreadsheet-config-form" :class="{ disabled: disabled }">
    <Tabs v-model:active-key="formSubTab">
      <Tabs.TabPane key="global" tab="全局设置">
        <Space wrap :size="12" class="global-settings">
          <span class="field-label">列宽</span>
          <InputNumber
            :disabled="disabled"
            :min="60"
            :value="config.defaultColWidth ?? 120"
            @update:value="(v) => patchConfig({ defaultColWidth: Number(v) || 120 })"
          />
          <span class="field-label">文字对齐</span>
          <Select
            :disabled="disabled"
            :options="textAlignOptions"
            :value="config.defaultTextAlign ?? 'left'"
            style="width: 88px"
            @update:value="(v) => patchConfig({ defaultTextAlign: v })"
          />
          <span class="field-label">行高</span>
          <Select
            :disabled="disabled"
            :options="[
              { label: '自动', value: 'auto' },
              { label: '固定', value: 'fixed' },
            ]"
            :value="rowHeightMode"
            style="width: 88px"
            @update:value="(v) => (rowHeightMode = v as 'auto' | 'fixed')"
          />
          <InputNumber
            v-if="rowHeightMode === 'fixed'"
            :disabled="disabled"
            :min="20"
            :value="rowHeightFixed"
            @update:value="(v) => (rowHeightFixed = Number(v) || 32)"
          />
          <span class="field-label">筛选</span>
          <Switch
            :checked="config.enableFilter !== false"
            :disabled="disabled"
            @update:checked="(v) => patchConfig({ enableFilter: v })"
          />
          <span class="field-label">历史</span>
          <Switch
            :checked="config.enableHistory !== false"
            :disabled="disabled"
            @update:checked="(v) => patchConfig({ enableHistory: v })"
          />
        </Space>
      </Tabs.TabPane>

      <Tabs.TabPane key="headers" tab="表头配置">
        <div class="table-toolbar">
          <Button :disabled="disabled" size="small" @click="addHeader">
            新增表头
          </Button>
        </div>
        <Table
          :columns="[
            { title: '列序号', dataIndex: 'col', width: 72 },
            { title: '标题', dataIndex: 'title', width: 120 },
            { title: '字段标识', dataIndex: 'fieldId', width: 120 },
            { title: '可筛选', dataIndex: 'filterable', width: 72 },
            { title: '固定列', dataIndex: 'fixed', width: 72 },
            { title: '表头颜色', dataIndex: 'headerColor', width: 100 },
            { title: '操作', dataIndex: 'action', width: 64 },
          ]"
          :data-source="config.headers.map((h, index) => ({ ...h, index, key: index }))"
          :pagination="false"
          bordered
          size="small"
        >
          <template #bodyCell="{ column, record }">
            <template v-if="column.dataIndex === 'col'">
              <InputNumber
                :disabled="disabled"
                :min="0"
                :value="record.col"
                size="small"
                @update:value="(v) => updateHeader(record.index, 'col', Number(v))"
              />
            </template>
            <template v-else-if="column.dataIndex === 'title'">
              <Input
                :disabled="disabled"
                :value="record.title"
                size="small"
                @update:value="(v) => updateHeader(record.index, 'title', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'fieldId'">
              <Input
                :disabled="disabled"
                :value="record.fieldId"
                size="small"
                @update:value="(v) => updateHeader(record.index, 'fieldId', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'filterable'">
              <Checkbox
                :checked="record.filterable !== false"
                :disabled="disabled"
                @update:checked="(v) => updateHeader(record.index, 'filterable', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'fixed'">
              <Checkbox
                :checked="!!record.fixed"
                :disabled="disabled"
                @update:checked="(v) => updateHeader(record.index, 'fixed', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'headerColor'">
              <Popover trigger="click" :disabled="disabled">
                <template #content>
                  <ColorPicker
                    :value="record.headerColor ?? ''"
                    @update:value="
                      (v) => updateHeader(record.index, 'headerColor', v || undefined)
                    "
                  />
                </template>
                <button
                  class="color-swatch-btn"
                  :disabled="disabled"
                  type="button"
                >
                  <span
                    class="color-swatch"
                    :style="{ backgroundColor: record.headerColor || '#e5e7eb' }"
                  />
                  <span class="color-swatch-label">
                    {{ record.headerColor || '选色' }}
                  </span>
                </button>
              </Popover>
            </template>
            <template v-else-if="column.dataIndex === 'action'">
              <Button
                danger
                :disabled="disabled"
                size="small"
                type="link"
                @click="removeHeader(record.index)"
              >
                删
              </Button>
            </template>
          </template>
        </Table>
      </Tabs.TabPane>

      <Tabs.TabPane key="columns" tab="列配置">
        <div class="table-toolbar">
          <Button :disabled="disabled" size="small" @click="addColumn">
            新增列
          </Button>
        </div>
        <Table
          :columns="[
            { title: '列序号', dataIndex: 'col', width: 64 },
            { title: '字段标识', dataIndex: 'fieldId', width: 100 },
            { title: '字段名称', dataIndex: 'fieldName', width: 96 },
            { title: '单元格类型', dataIndex: 'cellType', width: 100 },
            { title: '可编辑', dataIndex: 'editable', width: 64 },
            { title: '公式', dataIndex: 'formula', width: 130 },
            { title: '显示后缀', dataIndex: 'suffix', width: 80 },
            { title: '对齐', dataIndex: 'textAlign', width: 100 },
            { title: '大于阈值', dataIndex: 'gtThreshold', width: 88 },
            { title: '大于颜色', dataIndex: 'gtColor', width: 140 },
            { title: '小于阈值', dataIndex: 'ltThreshold', width: 88 },
            { title: '小于颜色', dataIndex: 'ltColor', width: 140 },
            { title: '操作', dataIndex: 'action', width: 56 },
          ]"
          :data-source="config.columns.map((c, index) => ({ ...c, index, key: index }))"
          :pagination="false"
          :scroll="{ x: 1200 }"
          bordered
          size="small"
        >
          <template #bodyCell="{ column, record }">
            <template v-if="column.dataIndex === 'col'">
              <InputNumber
                :disabled="disabled"
                :min="0"
                :value="record.col"
                size="small"
                @update:value="(v) => updateColumn(record.index, 'col', Number(v))"
              />
            </template>
            <template v-else-if="column.dataIndex === 'fieldId'">
              <Input
                :disabled="disabled"
                :value="record.fieldId"
                size="small"
                @update:value="(v) => updateColumn(record.index, 'fieldId', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'fieldName'">
              <Input
                :disabled="disabled"
                :value="record.fieldName"
                size="small"
                @update:value="(v) => updateColumn(record.index, 'fieldName', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'cellType'">
              <Select
                :disabled="disabled"
                :options="cellTypeOptions"
                :value="record.cellType"
                size="small"
                style="width: 92px"
                @update:value="(v) => updateColumn(record.index, 'cellType', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'editable'">
              <Checkbox
                :checked="record.editable !== false"
                :disabled="
                  disabled ||
                  record.cellType === 'formula' ||
                  record.cellType === 'readonly'
                "
                @update:checked="(v) => updateColumn(record.index, 'editable', v)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'formula'">
              <SpreadsheetFormulaField
                v-if="record.cellType === 'formula'"
                compact
                :disabled="disabled"
                :headers="config.headers"
                :model-value="record.formula ?? ''"
                @update:model-value="(v) => updateColumn(record.index, 'formula', v)"
              />
              <span v-else class="muted">—</span>
            </template>
            <template v-else-if="column.dataIndex === 'suffix'">
              <Input
                :disabled="disabled"
                :value="record.suffix ?? ''"
                placeholder="%"
                size="small"
                @update:value="(v) => updateColumn(record.index, 'suffix', v || undefined)"
              />
            </template>
            <template v-else-if="column.dataIndex === 'textAlign'">
              <Select
                :disabled="disabled"
                :options="columnTextAlignOptions"
                :value="record.textAlign ?? 'inherit'"
                size="small"
                style="width: 100%"
                @update:value="
                  (v) =>
                    updateColumn(
                      record.index,
                      'textAlign',
                      v === 'inherit' ? undefined : v,
                    )
                "
              />
            </template>
            <template v-else-if="column.dataIndex === 'gtThreshold'">
              <InputNumber
                v-if="showConditionalFields(record)"
                :disabled="disabled"
                :step="0.01"
                :value="record.conditionalFormat?.gt?.threshold"
                size="small"
                style="width: 72px"
                @update:value="
                  (v) => updateColumnConditional(record.index, 'gt', 'threshold', Number(v))
                "
              />
              <span v-else class="muted">—</span>
            </template>
            <template v-else-if="column.dataIndex === 'gtColor'">
              <div v-if="showConditionalFields(record)" class="color-rule-cell">
                <Select
                  :disabled="disabled"
                  :options="colorModeOptions"
                  size="small"
                  style="width: 72px; margin-bottom: 4px"
                  :value="conditionalColorMode(record, 'gt')"
                  @update:value="
                    (v) =>
                      updateColumnConditional(
                        record.index,
                        'gt',
                        'colorMode',
                        v,
                      )
                  "
                />
                <Popover
                  v-if="
                    conditionalColorMode(record, 'gt') !== 'text'
                  "
                  trigger="click"
                  :disabled="disabled"
                >
                  <template #content>
                    <ColorPicker
                      :value="record.conditionalFormat?.gt?.bgColor ?? ''"
                      @update:value="
                        (v) =>
                          updateColumnConditional(record.index, 'gt', 'bgColor', v)
                      "
                    />
                  </template>
                  <button
                    class="color-swatch-btn"
                    :disabled="disabled"
                    title="背景色"
                    type="button"
                  >
                    <span
                      class="color-swatch"
                      :style="{
                        backgroundColor:
                          record.conditionalFormat?.gt?.bgColor || '#e5e7eb',
                      }"
                    />
                  </button>
                </Popover>
                <Popover
                  v-if="
                    ['text', 'both'].includes(
                      conditionalColorMode(record, 'gt'),
                    )
                  "
                  trigger="click"
                  :disabled="disabled"
                >
                  <template #content>
                    <ColorPicker
                      :value="record.conditionalFormat?.gt?.textColor ?? ''"
                      @update:value="
                        (v) =>
                          updateColumnConditional(
                            record.index,
                            'gt',
                            'textColor',
                            v,
                          )
                      "
                    />
                  </template>
                  <button
                    class="color-swatch-btn"
                    :disabled="disabled"
                    title="文字色"
                    type="button"
                  >
                    <span
                      class="color-swatch color-swatch-text"
                      :style="{
                        color:
                          record.conditionalFormat?.gt?.textColor || '#111',
                      }"
                    >
                      A
                    </span>
                  </button>
                </Popover>
              </div>
              <span v-else class="muted">—</span>
            </template>
            <template v-else-if="column.dataIndex === 'ltThreshold'">
              <InputNumber
                v-if="showConditionalFields(record)"
                :disabled="disabled"
                :step="0.01"
                :value="record.conditionalFormat?.lt?.threshold"
                size="small"
                style="width: 72px"
                @update:value="
                  (v) => updateColumnConditional(record.index, 'lt', 'threshold', Number(v))
                "
              />
              <span v-else class="muted">—</span>
            </template>
            <template v-else-if="column.dataIndex === 'ltColor'">
              <div v-if="showConditionalFields(record)" class="color-rule-cell">
                <Select
                  :disabled="disabled"
                  :options="colorModeOptions"
                  size="small"
                  style="width: 72px; margin-bottom: 4px"
                  :value="conditionalColorMode(record, 'lt')"
                  @update:value="
                    (v) =>
                      updateColumnConditional(
                        record.index,
                        'lt',
                        'colorMode',
                        v,
                      )
                  "
                />
                <Popover
                  v-if="
                    conditionalColorMode(record, 'lt') !== 'text'
                  "
                  trigger="click"
                  :disabled="disabled"
                >
                  <template #content>
                    <ColorPicker
                      :value="record.conditionalFormat?.lt?.bgColor ?? ''"
                      @update:value="
                        (v) =>
                          updateColumnConditional(record.index, 'lt', 'bgColor', v)
                      "
                    />
                  </template>
                  <button
                    class="color-swatch-btn"
                    :disabled="disabled"
                    title="背景色"
                    type="button"
                  >
                    <span
                      class="color-swatch"
                      :style="{
                        backgroundColor:
                          record.conditionalFormat?.lt?.bgColor || '#e5e7eb',
                      }"
                    />
                  </button>
                </Popover>
                <Popover
                  v-if="
                    ['text', 'both'].includes(
                      conditionalColorMode(record, 'lt'),
                    )
                  "
                  trigger="click"
                  :disabled="disabled"
                >
                  <template #content>
                    <ColorPicker
                      :value="record.conditionalFormat?.lt?.textColor ?? ''"
                      @update:value="
                        (v) =>
                          updateColumnConditional(
                            record.index,
                            'lt',
                            'textColor',
                            v,
                          )
                      "
                    />
                  </template>
                  <button
                    class="color-swatch-btn"
                    :disabled="disabled"
                    title="文字色"
                    type="button"
                  >
                    <span
                      class="color-swatch color-swatch-text"
                      :style="{
                        color:
                          record.conditionalFormat?.lt?.textColor || '#111',
                      }"
                    >
                      A
                    </span>
                  </button>
                </Popover>
              </div>
              <span v-else class="muted">—</span>
            </template>
            <template v-else-if="column.dataIndex === 'action'">
              <Button
                danger
                :disabled="disabled"
                size="small"
                type="link"
                @click="removeColumn(record.index)"
              >
                删
              </Button>
            </template>
          </template>
        </Table>
      </Tabs.TabPane>
    </Tabs>
  </div>
</template>

<style scoped lang="scss">
.spreadsheet-config-form {
  &.disabled {
    opacity: 0.72;
    pointer-events: none;
  }
}

.global-settings {
  padding: 8px 0;
}

.field-label {
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}

.table-toolbar {
  margin-bottom: 8px;
}

.muted {
  color: hsl(var(--muted-foreground));
  opacity: 0.65;
}

.color-swatch-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 6px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
}

.color-swatch {
  display: inline-block;
  width: 18px;
  height: 18px;
  border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, 0.1);
}

.color-swatch-label {
  font-size: 12px;
  color: hsl(var(--muted-foreground));
  max-width: 72px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.color-rule-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}

.color-swatch-text {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  font-weight: 700;
  font-size: 12px;
}
</style>
