<script setup lang="ts">
import { computed, ref } from 'vue';
import type { VNode } from 'vue';
import { ElButton, ElCol, ElDatePicker, ElFormItem, ElInput, ElOption, ElRow, ElSelect } from 'element-plus';
import DictSelect from './dict-select.vue';

defineOptions({ name: 'TableSearchFields' });

interface Option {
  label: string;
  value: string | number;
}

export interface SearchField {
  /** 字段键名 */
  key: string;
  /** 字段标签 */
  label: string;
  /** 字段类型 */
  type: 'input' | 'select' | 'date' | 'dateRange' | 'dict';
  /** date 字段的日期粒度 */
  dateType?: 'date' | 'month';
  /** dateRange 字段的日期范围粒度 */
  dateRangeType?: 'daterange' | 'monthrange';
  /** 日期面板展示格式 */
  format?: string;
  /** 自定义范围分隔文案 */
  rangeSeparator?: string;
  /** 日期字段提交格式 */
  valueFormat?: string;
  /** 占位列数，默认 1 */
  span?: number;
  /** select 类型的选项 */
  options?: Option[];
  /** dict 类型的字典编码 */
  dictCode?: string;
  /** dict 类型下拉项右侧追加字典 remark 释义（如优先级 "P0 → 紧急"） */
  showRemark?: boolean;
  /** 占位提示文本 */
  placeholder?: string;
  /** select 类型的自定义选项渲染函数 */
  renderOption?: (option: Option) => VNode | VNode[] | string;
  /** select/dict 类型是否支持搜索 */
  filterable?: boolean;
  /** 值写回模型前的转换函数 */
  transformValue?: (value: any) => any;
  /** 从模型值解析展示值 */
  resolveValue?: (value: any) => any;
}

interface Props {
  /** 绑定表单数据对象 */
  modelValue: Record<string, any>;
  /** 查询字段定义数组 */
  fields: SearchField[];
  /** 每行格子数（按钮占 1 格） */
  columns: number;
  /** 表单标签宽度 */
  labelWidth?: string | number;
  /** 格子间距 */
  gutter?: number;
  /** 是否禁用 */
  disabled?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  labelWidth: 80,
  gutter: 16,
  disabled: false
});

interface Emits {
  (e: 'search'): void;
  (e: 'reset'): void;
}

const emit = defineEmits<Emits>();

// 折叠/展开状态
const expanded = ref(false);

// 是否需要折叠（字段数 > columns - 1）
const needsCollapse = computed(() => props.fields.length > props.columns - 1);

// 第一行字段数（留一个位置给按钮）
const firstRowFieldCount = computed(() => props.columns - 1);

// 计算第一行字段
const firstRowFields = computed(() => {
  if (expanded.value || !needsCollapse.value) {
    return props.fields.slice(0, firstRowFieldCount.value);
  }
  return props.fields.slice(0, firstRowFieldCount.value);
});

// 计算后续行字段（用于展开后显示）
const remainingFields = computed(() => {
  if (expanded.value || !needsCollapse.value) {
    return props.fields.slice(firstRowFieldCount.value);
  }
  return [];
});

const firstRowButtonSpan = computed(() => {
  return Math.floor(24 / props.columns);
});

// 计算第一行字段的 span（字段和按钮区保持同一列宽）
const firstRowFieldSpan = computed(() => {
  return firstRowButtonSpan.value;
});

// 计算每个字段的 span（用于后续行）
const fieldSpan = computed(() => {
  return Math.floor(24 / props.columns);
});

// 字段不足时补足首行空列，确保按钮区始终落在 columns 定义的最后一格。
const firstRowPlaceholderSpan = computed(() => {
  const emptySlotCount = Math.max(props.columns - 1 - firstRowFields.value.length, 0);
  return emptySlotCount * fieldSpan.value;
});

function handleToggle() {
  expanded.value = !expanded.value;
}

function handleReset() {
  emit('reset');
}

function handleSearch() {
  emit('search');
}

function updateFieldValue(field: SearchField, value: any) {
  // eslint-disable-next-line vue/no-mutating-props
  props.modelValue[field.key] = field.transformValue ? field.transformValue(value) : value;
}

function getFieldValue(field: SearchField) {
  const value = props.modelValue[field.key];
  return field.resolveValue ? field.resolveValue(value) : value;
}
</script>

<!-- eslint-disable vue/no-mutating-props -->
<template>
  <ElCard class="card-wrapper">
    <ElForm :model="props.modelValue" :label-width="props.labelWidth" @submit.prevent @keyup.enter="handleSearch">
      <!-- 第一行：fields + 按钮 -->
      <ElRow :gutter="props.gutter">
        <ElCol
          v-for="field in firstRowFields"
          :key="field.key"
          class="table-search-fields__col"
          :span="firstRowFieldSpan"
        >
          <ElFormItem :label="field.label">
            <ElInput
              v-if="field.type === 'input'"
              :model-value="getFieldValue(field)"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <ElSelect
              v-else-if="field.type === 'select'"
              :model-value="getFieldValue(field)"
              :placeholder="field.placeholder"
              clearable
              :filterable="field.filterable"
              :disabled="props.disabled"
              @update:model-value="val => updateFieldValue(field, val)"
            >
              <ElOption v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value">
                <template v-if="field.renderOption" #default>
                  <component :is="field.renderOption(opt)" />
                </template>
              </ElOption>
            </ElSelect>
            <ElDatePicker
              v-else-if="field.type === 'date'"
              :model-value="getFieldValue(field)"
              :type="field.dateType || 'date'"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              :format="field.format"
              :value-format="field.valueFormat || 'YYYY-MM-DD'"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <ElDatePicker
              v-else-if="field.type === 'dateRange'"
              :model-value="getFieldValue(field)"
              :type="field.dateRangeType || 'daterange'"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              :format="field.format"
              :value-format="field.valueFormat || 'YYYY-MM-DD'"
              :range-separator="field.rangeSeparator || '至'"
              :start-placeholder="field.dateRangeType === 'monthrange' ? '开始月份' : '开始日期'"
              :end-placeholder="field.dateRangeType === 'monthrange' ? '结束月份' : '结束日期'"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <DictSelect
              v-else-if="field.type === 'dict'"
              :model-value="getFieldValue(field)"
              :dict-code="field.dictCode!"
              :placeholder="field.placeholder"
              :filterable="field.filterable"
              :disabled="props.disabled"
              :show-remark="field.showRemark"
              @update:model-value="val => updateFieldValue(field, val)"
            />
          </ElFormItem>
        </ElCol>

        <ElCol
          v-if="firstRowPlaceholderSpan > 0"
          class="table-search-fields__col table-search-fields__placeholder-col"
          :span="firstRowPlaceholderSpan"
          aria-hidden="true"
        />

        <!-- 按钮区域 -->
        <ElCol class="table-search-fields__col table-search-fields__action-col" :span="firstRowButtonSpan">
          <ElFormItem class="table-search-fields__actions" label-width="0">
            <ElButton
              v-if="needsCollapse"
              circle
              :title="expanded ? '收起' : '展开'"
              :aria-label="expanded ? '收起查询条件' : '展开查询条件'"
              :disabled="props.disabled"
              @click="handleToggle"
            >
              <icon-mdi-chevron-double-up v-if="expanded" />
              <icon-mdi-chevron-double-down v-else />
            </ElButton>
            <ElButton :disabled="props.disabled" @click="handleReset">
              <template #icon>
                <icon-ic-round-refresh class="text-icon" />
              </template>
              重置
            </ElButton>
            <ElButton type="primary" :disabled="props.disabled" @click="handleSearch">
              <template #icon>
                <icon-ic-round-search class="text-icon" />
              </template>
              查询
            </ElButton>
          </ElFormItem>
        </ElCol>
      </ElRow>

      <!-- 展开后的后续行 -->
      <ElRow v-if="expanded && remainingFields.length > 0" :gutter="props.gutter">
        <ElCol v-for="field in remainingFields" :key="field.key" class="table-search-fields__col" :span="fieldSpan">
          <ElFormItem :label="field.label">
            <ElInput
              v-if="field.type === 'input'"
              :model-value="getFieldValue(field)"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <ElSelect
              v-else-if="field.type === 'select'"
              :model-value="getFieldValue(field)"
              :placeholder="field.placeholder"
              clearable
              :filterable="field.filterable"
              :disabled="props.disabled"
              @update:model-value="val => updateFieldValue(field, val)"
            >
              <ElOption v-for="opt in field.options" :key="opt.value" :label="opt.label" :value="opt.value">
                <template v-if="field.renderOption" #default>
                  <component :is="field.renderOption(opt)" />
                </template>
              </ElOption>
            </ElSelect>
            <ElDatePicker
              v-else-if="field.type === 'date'"
              :model-value="getFieldValue(field)"
              :type="field.dateType || 'date'"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              :format="field.format"
              :value-format="field.valueFormat || 'YYYY-MM-DD'"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <ElDatePicker
              v-else-if="field.type === 'dateRange'"
              :model-value="getFieldValue(field)"
              :type="field.dateRangeType || 'daterange'"
              :placeholder="field.placeholder"
              clearable
              :disabled="props.disabled"
              :format="field.format"
              :value-format="field.valueFormat || 'YYYY-MM-DD'"
              :range-separator="field.rangeSeparator || '至'"
              :start-placeholder="field.dateRangeType === 'monthrange' ? '开始月份' : '开始日期'"
              :end-placeholder="field.dateRangeType === 'monthrange' ? '结束月份' : '结束日期'"
              @update:model-value="val => updateFieldValue(field, val)"
            />
            <DictSelect
              v-else-if="field.type === 'dict'"
              :model-value="getFieldValue(field)"
              :dict-code="field.dictCode!"
              :placeholder="field.placeholder"
              :filterable="field.filterable"
              :disabled="props.disabled"
              :show-remark="field.showRemark"
              @update:model-value="val => updateFieldValue(field, val)"
            />
          </ElFormItem>
        </ElCol>
      </ElRow>
    </ElForm>
  </ElCard>
</template>

<style scoped lang="scss">
:deep(.el-form-item) {
  display: flex;
  align-items: center;
}

.table-search-fields__col {
  min-width: 0;
}

.table-search-fields__placeholder-col {
  pointer-events: none;
}

.table-search-fields__actions {
  :deep(.el-form-item__content) {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: 8px;
    min-width: 0;
  }

  :deep(.el-button + .el-button) {
    margin-left: 0;
  }
}

:deep(.el-form-item__content) {
  min-width: 0;
}

:deep(.el-input),
:deep(.el-select),
:deep(.el-date-editor) {
  width: 100%;
  min-width: 0;
}
</style>
