<script setup lang="ts">
import { computed, nextTick, onMounted, ref } from 'vue';
import { ElCol, ElDatePicker, ElFormItem, ElInput, ElOption, ElRow, ElSelect } from 'element-plus';
import dayjs from 'dayjs';
import { RDMS_OBJECT_DIRECTION_DICT_CODE, RDMS_PROJECT_TYPE_DICT_CODE } from '@/constants/dict';
import { fetchGetProductPage } from '@/service/api';
import { useDict } from '@/hooks/business/dict';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessUserSelect from '@/components/custom/business-user-select.vue';
import DictSelect from '@/components/custom/dict-select.vue';

defineOptions({ name: 'ProjectCreateBaseForm' });

export interface ProjectCreateBaseForm {
  projectCode: string;
  projectName: string;
  directionCode: string;
  projectType: string;
  productId: string | null;
  managerUserId: string | null;
  plannedStartDate: string | null;
  plannedEndDate: string | null;
  projectDesc: string;
}

interface ProductOption {
  id: string;
  name: string;
  directionCode: string;
}

interface Props {
  managerUserOptions: Api.SystemManage.UserSimple[];
}

defineProps<Props>();

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

const { formRef, validate } = useForm();
const { createRequiredRule } = useFormRules();
const { getLabel: getDirectionLabel } = useDict(RDMS_OBJECT_DIRECTION_DICT_CODE);

const productOptions = ref<ProductOption[]>([]);

const hasAssociatedProduct = computed(() => Boolean(model.value.productId));
const directionReadonly = computed(() => hasAssociatedProduct.value);

const selectedProductDirection = computed(() => {
  if (!model.value.productId) {
    return '';
  }

  return productOptions.value.find(p => p.id === model.value.productId)?.directionCode || '';
});

const effectiveDirectionCode = computed({
  get: () => {
    if (hasAssociatedProduct.value) {
      return selectedProductDirection.value || model.value.directionCode;
    }

    return model.value.directionCode;
  },
  set: (val: string) => {
    if (!hasAssociatedProduct.value) {
      model.value.directionCode = val;
    }
  }
});

const directionDisplayName = computed(() => {
  const directionCode = effectiveDirectionCode.value;

  if (!directionCode) {
    return '';
  }

  return getDirectionLabel(directionCode, directionCode);
});

function parsePlannedDate(value: string | null | undefined) {
  if (!value) {
    return null;
  }

  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? null : date;
}

function isPlannedDateRangeValid(startDate: string | null, endDate: string | null) {
  if (!startDate || !endDate) {
    return true;
  }

  return !dayjs(endDate).isBefore(dayjs(startDate), 'day');
}

function buildEndDateShortcut(text: string, mutator: (date: Date) => void) {
  return {
    text,
    value: () => {
      let startDate = parsePlannedDate(model.value.plannedStartDate);

      if (!startDate) {
        startDate = new Date();
        model.value.plannedStartDate = dayjs(startDate).format('YYYY-MM-DD');
        window.$message?.info('未选择计划开始日期，已按今日为基准计算');
        nextTick(() => formRef.value?.clearValidate('plannedStartDate'));
      }

      const endDate = new Date(startDate.getTime());
      mutator(endDate);
      return endDate;
    }
  };
}

const plannedEndDateShortcuts = [
  buildEndDateShortcut('一星期', date => date.setDate(date.getDate() + 7)),
  buildEndDateShortcut('两星期', date => date.setDate(date.getDate() + 14)),
  buildEndDateShortcut('一个月', date => date.setMonth(date.getMonth() + 1)),
  buildEndDateShortcut('三个月', date => date.setMonth(date.getMonth() + 3)),
  buildEndDateShortcut('半年', date => date.setMonth(date.getMonth() + 6)),
  buildEndDateShortcut('一年', date => date.setFullYear(date.getFullYear() + 1))
];

const rules = computed(
  () =>
    ({
      projectName: [createRequiredRule('请输入项目名称')],
      directionCode: [createRequiredRule('请选择项目方向')],
      projectType: [createRequiredRule('请选择项目类型')],
      managerUserId: [createRequiredRule('请选择项目经理')],
      plannedStartDate: [createRequiredRule('请选择计划开始日期')],
      plannedEndDate: [
        createRequiredRule('请选择计划结束日期'),
        {
          validator: (_rule, value: string | null, callback) => {
            if (!isPlannedDateRangeValid(model.value.plannedStartDate, value)) {
              callback(new Error('计划结束日期不能早于计划开始日期'));
              return;
            }

            callback();
          },
          trigger: 'change'
        }
      ]
    }) satisfies Record<string, App.Global.FormRule[]>
);

async function loadProductOptions() {
  const { error, data } = await fetchGetProductPage({ pageNo: 1, pageSize: 200 });

  if (error || !data) {
    productOptions.value = [];
    return;
  }

  productOptions.value = data.list.map(item => ({
    id: item.id,
    name: item.name || item.code || item.id,
    directionCode: item.directionCode || ''
  }));
}

function onProductChange(newProductId: string | null) {
  if (!newProductId) {
    return;
  }

  const product = productOptions.value.find(p => p.id === newProductId);

  if (product) {
    model.value.directionCode = product.directionCode;
  }
}

async function runValidate(): Promise<boolean> {
  try {
    await validate();
    return true;
  } catch {
    return false;
  }
}

onMounted(loadProductOptions);

defineExpose({ validate: runValidate });
</script>

<template>
  <ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
    <ElRow :gutter="16">
      <ElCol :span="12">
        <ElFormItem label="项目名称" prop="projectName">
          <ElInput v-model="model.projectName" clearable maxlength="128" placeholder="请输入项目名称" />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="项目编码" prop="projectCode">
          <ElInput v-model="model.projectCode" clearable placeholder="不填则由后端自动生成" />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="项目方向" prop="directionCode">
          <DictSelect
            v-if="!directionReadonly"
            v-model="effectiveDirectionCode"
            :dict-code="RDMS_OBJECT_DIRECTION_DICT_CODE"
            filterable
            placeholder="请选择项目方向"
          />
          <ElInput
            v-else
            :model-value="directionDisplayName"
            readonly
            class="project-create-base-form__readonly-input"
            placeholder="未获取到项目方向"
          />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="项目类型" prop="projectType">
          <DictSelect
            v-model="model.projectType"
            :dict-code="RDMS_PROJECT_TYPE_DICT_CODE"
            filterable
            placeholder="请选择项目类型"
          />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="所属产品" prop="productId">
          <ElSelect
            v-model="model.productId"
            clearable
            filterable
            placeholder="选择所属产品（可选），选择后将锁定项目方向"
            @change="onProductChange"
          >
            <ElOption v-for="item in productOptions" :key="item.id" :label="item.name" :value="item.id" />
          </ElSelect>
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="项目经理" prop="managerUserId">
          <BusinessUserSelect
            v-model="model.managerUserId"
            :options="managerUserOptions"
            placeholder="请选择项目经理"
          />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="计划开始日期" prop="plannedStartDate">
          <ElDatePicker
            v-model="model.plannedStartDate"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="选择开始日期"
            class="project-create-base-form__date-picker"
          />
        </ElFormItem>
      </ElCol>
      <ElCol :span="12">
        <ElFormItem label="计划结束日期" prop="plannedEndDate">
          <ElDatePicker
            v-model="model.plannedEndDate"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="选择结束日期"
            :shortcuts="plannedEndDateShortcuts"
            class="project-create-base-form__date-picker"
          />
        </ElFormItem>
      </ElCol>
      <ElCol :span="24">
        <ElFormItem label="项目说明" prop="projectDesc">
          <ElInput
            v-model="model.projectDesc"
            type="textarea"
            :rows="4"
            maxlength="500"
            show-word-limit
            placeholder="请输入项目说明"
          />
        </ElFormItem>
      </ElCol>
    </ElRow>
  </ElForm>
</template>

<style scoped>
:deep(.project-create-base-form__readonly-input .el-input__wrapper) {
  background: linear-gradient(180deg, rgb(241 245 249 / 98%), rgb(226 232 240 / 94%)), rgb(241 245 249);
  box-shadow: 0 0 0 1px rgb(203 213 225 / 96%) inset;
  cursor: default;
}

:deep(.project-create-base-form__readonly-input .el-input__wrapper:hover),
:deep(.project-create-base-form__readonly-input.is-focus .el-input__wrapper) {
  box-shadow: 0 0 0 1px rgb(203 213 225 / 96%) inset;
}

:deep(.project-create-base-form__readonly-input .el-input__inner) {
  color: rgb(51 65 85 / 96%);
  cursor: default;
  -webkit-text-fill-color: rgb(51 65 85 / 96%);
}

:deep(.project-create-base-form__date-picker.el-date-editor.el-input) {
  width: 100%;
}
</style>
