<script setup lang="tsx">
import { computed, nextTick, ref, watch } 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 { fetchCreateProject, fetchGetProductPage, fetchUpdateProject } from '@/service/api';
import { useDict } from '@/hooks/business/dict';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import BusinessFormSection from '@/components/custom/business-form-section.vue';
import BusinessUserSelect from '@/components/custom/business-user-select.vue';
import DictSelect from '@/components/custom/dict-select.vue';

defineOptions({ name: 'ProjectOperateDialog' });

interface Props {
  managerUserOptions: Api.SystemManage.UserSimple[];
  rowData?: Api.Project.Project | null;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'submitted', projectId?: string): void;
}

const emit = defineEmits<Emits>();

const visible = defineModel<boolean>('visible', {
  default: false
});

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

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

const isEditMode = computed(() => Boolean(props.rowData?.id));
const dialogTitle = computed(() => (isEditMode.value ? '编辑项目' : '新增项目'));
const submitting = ref(false);
const loading = ref(false);
const model = ref<Model>(createDefaultModel());

// 产品选项，包含 ID、名称、方向
interface ProductOption {
  id: string;
  name: string;
  directionCode: string;
}

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

const managerLabelMap = computed(() => new Map(props.managerUserOptions.map(item => [String(item.id), item.nickname])));
const managerDisplayName = computed(() => {
  const managerUserId = model.value.managerUserId;
  if (!managerUserId) {
    return '';
  }
  return managerLabelMap.value.get(String(managerUserId)) || String(managerUserId);
});

// 当前选中产品的方向
const selectedProductDirection = computed(() => {
  if (!model.value.productId) {
    return '';
  }
  const product = productOptions.value.find(p => p.id === model.value.productId);
  return product?.directionCode || '';
});

// 判断是否关联了产品（创建/编辑模式都适用）
const hasAssociatedProduct = computed(() => Boolean(model.value.productId));

// 方向字段是否只读：关联了产品时只读，未关联时可编辑
const directionReadonly = computed(() => hasAssociatedProduct.value);

// 当前生效的方向：关联产品则用产品方向，否则用用户选择的方向
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 productOptionLabel = (item: ProductOption) => {
  return `${item.name}`;
};

const rules = {
  projectName: [createRequiredRule('请输入项目名称')],
  directionCode: [createRequiredRule('请选择项目方向')],
  projectType: [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[]>;

function createDefaultModel(): Model {
  return {
    projectCode: '',
    projectName: '',
    directionCode: '',
    projectType: '',
    productId: null,
    managerUserId: null,
    plannedStartDate: null,
    plannedEndDate: null,
    projectDesc: ''
  };
}

function getNullableText(value?: string | null) {
  return value?.trim() || null;
}

function closeDialog() {
  visible.value = false;
}

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 || ''
  }));
}

// 监听产品选择变化，联动方向（创建模式）
watch(
  () => model.value.productId,
  (newProductId, oldProductId) => {
    if (isEditMode.value) {
      return; // 编辑模式下不处理，产品字段只读
    }

    if (newProductId && newProductId !== oldProductId) {
      // 选择了产品，自动填充方向
      const product = productOptions.value.find(p => p.id === newProductId);
      if (product) {
        model.value.directionCode = product.directionCode;
      }
    }
    // 取消选择产品时，directionCode 保留，用户可重新选择
  }
);

async function handleSubmit() {
  await validate();

  // 提交时，如果关联了产品，使用产品方向
  const finalDirectionCode = hasAssociatedProduct.value
    ? selectedProductDirection.value || model.value.directionCode
    : model.value.directionCode;

  const payload: Api.Project.SaveProjectParams = {
    projectCode: getNullableText(model.value.projectCode),
    projectName: model.value.projectName.trim(),
    directionCode: finalDirectionCode,
    projectType: model.value.projectType,
    productId: model.value.productId,
    managerUserId: model.value.managerUserId || '',
    plannedStartDate: model.value.plannedStartDate,
    plannedEndDate: model.value.plannedEndDate,
    actualStartDate: isEditMode.value ? props.rowData?.actualStartDate || null : undefined,
    actualEndDate: isEditMode.value ? props.rowData?.actualEndDate || null : undefined,
    projectDesc: getNullableText(model.value.projectDesc)
  };

  submitting.value = true;

  if (isEditMode.value && props.rowData?.id) {
    const updateParams: Api.Project.UpdateProjectParams = {
      id: props.rowData.id,
      ...payload
    };

    const result = await fetchUpdateProject(updateParams);

    submitting.value = false;

    if (result.error) {
      return;
    }

    window.$message?.success('项目编辑成功');
    closeDialog();
    emit('submitted', props.rowData.id);
    return;
  }

  const result = await fetchCreateProject(payload);

  submitting.value = false;

  if (result.error) {
    return;
  }

  window.$message?.success('项目新增成功');
  closeDialog();
  emit('submitted', result.data);
}

watch(visible, async value => {
  if (!value) {
    return;
  }

  await loadProductOptions();

  if (!isEditMode.value || !props.rowData?.id) {
    model.value = createDefaultModel();
    await nextTick();
    formRef.value?.clearValidate();
    return;
  }

  model.value = {
    projectCode: props.rowData.projectCode || '',
    projectName: props.rowData.projectName || '',
    directionCode: props.rowData.directionCode || '',
    projectType: props.rowData.projectType || '',
    productId: props.rowData.productId,
    managerUserId: props.rowData.managerUserId || null,
    plannedStartDate: props.rowData.plannedStartDate,
    plannedEndDate: props.rowData.plannedEndDate,
    projectDesc: props.rowData.projectDesc || ''
  };

  await nextTick();
  formRef.value?.clearValidate();
});
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    :title="dialogTitle"
    preset="md"
    :loading="loading"
    :confirm-loading="submitting"
    @confirm="handleSubmit"
  >
    <ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
      <BusinessFormSection title="项目信息">
        <ElRow :gutter="16">
          <ElCol :span="12">
            <ElFormItem v-if="isEditMode" label="项目编码" prop="projectCode">
              <ElInput
                :model-value="model.projectCode"
                readonly
                class="project-operate-dialog__readonly-input"
                placeholder="未获取到项目编码"
              />
            </ElFormItem>
            <ElFormItem v-else label="项目编码" prop="projectCode">
              <ElInput v-model="model.projectCode" clearable placeholder="不填则由后端自动生成" />
            </ElFormItem>
          </ElCol>
          <ElCol :span="12">
            <ElFormItem label="项目名称" prop="projectName">
              <ElInput v-model="model.projectName" clearable maxlength="128" 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-operate-dialog__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 v-if="isEditMode" label="所属产品">
              <ElInput
                :model-value="
                  productOptions.find(p => p.id === model.productId)?.name ||
                  props.rowData?.productName ||
                  model.productId ||
                  '未关联产品'
                "
                readonly
                class="project-operate-dialog__readonly-input"
                placeholder="未关联产品"
              />
            </ElFormItem>
            <ElFormItem v-else label="所属产品" prop="productId">
              <ElSelect
                v-model="model.productId"
                clearable
                filterable
                placeholder="选择所属产品（可选），选择后将锁定项目方向"
              >
                <ElOption
                  v-for="item in productOptions"
                  :key="item.id"
                  :label="productOptionLabel(item)"
                  :value="item.id"
                />
              </ElSelect>
            </ElFormItem>
          </ElCol>
          <ElCol :span="12">
            <ElFormItem v-if="isEditMode">
              <template #label>
                <span class="business-form-label-with-tip">
                  <ElTooltip
                    content="如需调整项目经理，请到项目内的团队管理处处理。"
                    popper-class="business-form-label-tooltip"
                    placement="top-start"
                  >
                    <span class="business-form-label-tip">
                      <icon-fe:question />
                    </span>
                  </ElTooltip>
                  <span>项目经理</span>
                </span>
              </template>
              <ElInput
                :model-value="managerDisplayName"
                readonly
                class="project-operate-dialog__readonly-input"
                placeholder="未获取到项目经理"
              />
            </ElFormItem>
            <ElFormItem v-else 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-operate-dialog__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-operate-dialog__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>
      </BusinessFormSection>
    </ElForm>
  </BusinessFormDialog>
</template>

<style scoped>
:deep(.project-operate-dialog__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-operate-dialog__readonly-input .el-input__wrapper:hover),
:deep(.project-operate-dialog__readonly-input.is-focus .el-input__wrapper) {
  box-shadow: 0 0 0 1px rgb(203 213 225 / 96%) inset;
}

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

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