<script setup lang="ts">
/* eslint-disable no-void */
import { computed, onMounted, ref, watch } from 'vue';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek';
import { fetchGetWorkReportStatusDict } from '@/service/api';
import type { SearchField } from '@/components/custom/table-search-fields.vue';
import TableSearchFields from '@/components/custom/table-search-fields.vue';
import { BOOLEAN_TRUE_FALSE_OPTIONS, type WorkReportSearchParams, type WorkReportType } from '../types';
import { normalizeWeeklySearchRange } from '../utils';

dayjs.extend(isoWeek);

defineOptions({ name: 'WorkReportSearch' });

interface Props {
  reportType: WorkReportType;
  teamMode?: boolean;
  subordinateOptions?: Array<{ label: string; value: string }>;
  projectOptions?: Api.WorkReport.Project.ProjectReportOwnerProjectOption[];
}

const props = withDefaults(defineProps<Props>(), {
  teamMode: false,
  subordinateOptions: () => [],
  projectOptions: () => []
});

const model = defineModel<WorkReportSearchParams>('model', { required: true });

const emit = defineEmits<{
  (e: 'reset'): void;
  (e: 'search'): void;
}>();

const statusDict = ref<Api.WorkReport.Common.WorkReportStatusDict[]>([]);

const statusOptions = computed(() =>
  [...statusDict.value]
    .sort((a, b) => Number(a.sort || 0) - Number(b.sort || 0))
    .map(item => ({
      label: item.statusName || item.statusCode,
      value: item.statusCode
    }))
);

const projectPeriodDraftStartDate = ref('');

function parseProjectPeriodStartDate() {
  const startDate = projectPeriodDraftStartDate.value || (model.value.periodStartDate as string[] | undefined)?.[0];
  const parsed = dayjs(startDate);
  return parsed.isValid() ? parsed.toDate() : new Date();
}

function handleProjectPeriodCalendarChange(value: unknown) {
  const startDate = Array.isArray(value) ? value[0] : '';
  const parsed = dayjs(startDate);
  projectPeriodDraftStartDate.value = parsed.isValid() ? parsed.format('YYYY-MM-DD') : '';
}

function handleProjectPeriodVisibleChange(visible: boolean) {
  if (!visible) {
    projectPeriodDraftStartDate.value = '';
  }
}

function buildProjectPeriodShortcut(text: string, mutator: (date: Date) => void) {
  return {
    text,
    value: () => {
      const startDate = parseProjectPeriodStartDate();
      const endDate = new Date(startDate.getTime());
      mutator(endDate);
      return [startDate, endDate] as [Date, Date];
    }
  };
}

const projectPeriodShortcuts = [
  buildProjectPeriodShortcut('两星期', date => date.setDate(date.getDate() + 14)),
  buildProjectPeriodShortcut('三星期', date => date.setDate(date.getDate() + 21)),
  buildProjectPeriodShortcut('一个月', date => date.setMonth(date.getMonth() + 1))
];

const fields = computed<SearchField[]>(() => {
  const baseFields: SearchField[] = [
    { key: 'statusCode', label: '状态', type: 'select', options: statusOptions.value, placeholder: '请选择状态' },
    { key: 'periodStartDate', label: '周期', type: 'dateRange', placeholder: '请选择周期' }
  ];

  const monthPeriodField: SearchField = {
    key: 'periodStartDate',
    label: '月份',
    type: 'dateRange',
    dateRangeType: 'monthrange',
    valueFormat: 'YYYY-MM-DD',
    placeholder: '请选择月份'
  };

  if (props.reportType === 'weekly') {
    const weeklyPeriodField: SearchField = {
      key: 'periodStartDate',
      label: '周期',
      type: 'weekRangePair'
    };

    const teamReporterField: SearchField[] = props.teamMode
      ? [
          {
            key: 'reporterIds',
            label: '提交人',
            type: 'select',
            options: props.subordinateOptions,
            placeholder: '请选择提交人',
            filterable: true,
            transformValue: value => (value ? [value] : undefined),
            resolveValue: value => (Array.isArray(value) ? value[0] : value)
          }
        ]
      : [];

    return [
      baseFields[0],
      weeklyPeriodField,
      ...teamReporterField,
      {
        key: 'isBusinessTrip',
        label: '是否出差',
        type: 'select',
        options: BOOLEAN_TRUE_FALSE_OPTIONS,
        placeholder: '请选择'
      }
    ];
  }

  if (props.reportType === 'project') {
    return [
      baseFields[0],
      {
        key: 'periodStartDate',
        label: '周期',
        type: 'dateRange',
        placeholder: '请选择周期',
        shortcuts: projectPeriodShortcuts,
        onCalendarChange: handleProjectPeriodCalendarChange,
        onVisibleChange: handleProjectPeriodVisibleChange
      },
      {
        key: 'projectId',
        label: '项目',
        type: 'select',
        options: props.projectOptions.map(item => ({
          label: item.projectCode ? `${item.projectName}（${item.projectCode}）` : item.projectName,
          value: item.id
        })),
        placeholder: '请选择项目',
        filterable: true
      }
    ];
  }

  if (props.reportType === 'monthly') {
    const teamReporterField: SearchField[] = props.teamMode
      ? [
          {
            key: 'reporterIds',
            label: '提交人',
            type: 'select',
            options: props.subordinateOptions,
            placeholder: '请选择提交人',
            filterable: true,
            transformValue: value => (value ? [value] : undefined),
            resolveValue: value => (Array.isArray(value) ? value[0] : value)
          }
        ]
      : [];

    return [baseFields[0], monthPeriodField, ...teamReporterField];
  }

  return baseFields;
});

async function loadStatusDict() {
  const { error, data } = await fetchGetWorkReportStatusDict();
  statusDict.value = error || !data ? [] : data;
}

onMounted(() => {
  loadStatusDict();
});

watch(
  () => props.reportType,
  type => {
    if (type !== 'weekly') return;
    model.value.periodStartDate = normalizeWeeklySearchRange(model.value.periodStartDate as string[] | undefined);
  },
  { immediate: true }
);

watch(
  () => model.value.periodStartDate,
  value => {
    if (props.reportType === 'project') {
      if (!Array.isArray(value) || !value[0]) {
        projectPeriodDraftStartDate.value = '';
      }
      return;
    }

    if (props.reportType !== 'weekly') return;

    const normalizedValue = normalizeWeeklySearchRange(value as string[] | undefined);
    const currentValue = Array.isArray(value) ? value : [];

    if (
      normalizedValue?.length === currentValue.length &&
      normalizedValue?.every((item, index) => item === currentValue[index])
    ) {
      return;
    }

    model.value.periodStartDate = normalizedValue;
  }
);
</script>

<template>
  <TableSearchFields v-model="model" :columns="4" :fields="fields" @reset="emit('reset')" @search="emit('search')" />
</template>
