<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue';
import { ElMessageBox } from 'element-plus';
import {
  fetchCreateMonthlyReport,
  fetchCreateProjectReport,
  fetchCreateWeeklyReport,
  fetchGetMonthlyReportDetail,
  fetchGetProjectReportDetail,
  fetchGetWeeklyReportDetail,
  fetchInitMonthlyReport,
  fetchInitProjectReport,
  fetchInitWeeklyReport,
  fetchPreviewMonthlyReportDefaultDraft,
  fetchPreviewProjectReportDefaultDraft,
  fetchPreviewWeeklyReportDefaultDraft,
  fetchRefreshMonthlyReportDraft,
  fetchRefreshProjectReportDraft,
  fetchRefreshWeeklyReportDraft,
  fetchUpdateMonthlyReport,
  fetchUpdateProjectReport,
  fetchUpdateWeeklyReport
} from '@/service/api';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import BusinessFormSection from '@/components/custom/business-form-section.vue';
import {
  WORK_REPORT_TYPE_LABEL,
  type WorkReportRow,
  type WorkReportType,
  createBlankPlanItem,
  createBlankProjectItem,
  createBlankReviewItem,
  createMonthlySaveParams,
  createProjectSaveParams,
  createWeeklySaveParams,
  normalizePlanItems,
  normalizeProjectItems,
  normalizeReviewItems
} from '../types';

defineOptions({ name: 'WorkReportOperateDialog' });

interface PeriodPayload {
  periodKey: string;
  periodLabel: string;
  periodStartDate: string;
  periodEndDate: string;
}

interface Props {
  operateType: 'add' | 'edit';
  reportType: WorkReportType;
  rowData?: WorkReportRow | null;
  initialPeriod?: PeriodPayload | null;
  initialProjectId?: string;
  initialFlag?: number;
}

const props = withDefaults(defineProps<Props>(), {
  rowData: null,
  initialPeriod: null,
  initialProjectId: '',
  initialFlag: 1
});

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

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

const loading = ref(false);
const submitting = ref(false);
const baseInfo = ref<WorkReportRow | null>(null);

const weeklyModel = reactive<Api.WorkReport.Weekly.WeeklyReportSaveParams>(createWeeklySaveParams());
const monthlyModel = reactive<Api.WorkReport.Monthly.MonthlyReportSaveParams>(createMonthlySaveParams());
const projectModel = reactive<Api.WorkReport.Project.ProjectReportSaveParams>(createProjectSaveParams());

const title = computed(
  () => `${props.operateType === 'add' ? '新增' : '编辑'}${WORK_REPORT_TYPE_LABEL[props.reportType]}`
);
const dialogPreset = computed(() => (props.reportType === 'weekly' ? 'md' : 'lg'));
const activeModel = computed(() => {
  if (props.reportType === 'monthly') return monthlyModel;
  if (props.reportType === 'project') return projectModel;
  return weeklyModel;
});
const baseReporterName = computed(() => {
  if (!baseInfo.value) return '--';
  if ('projectOwnerName' in baseInfo.value) return baseInfo.value.projectOwnerName || '--';
  return baseInfo.value.reporterName || '--';
});
const baseDeptName = computed(() => {
  if (!baseInfo.value || 'projectOwnerName' in baseInfo.value) return '--';
  return baseInfo.value.reporterDeptName || '--';
});
const basePostName = computed(() => {
  if (!baseInfo.value || 'projectOwnerName' in baseInfo.value) return '--';
  return baseInfo.value.reporterPostName || '--';
});

function patchPeriod(target: {
  periodKey: string;
  periodLabel: string;
  periodStartDate: string;
  periodEndDate: string;
}) {
  if (!props.initialPeriod) return;
  Object.assign(target, props.initialPeriod);
}

function patchWeekly(report?: Partial<Api.WorkReport.Weekly.WeeklyReport>) {
  Object.assign(
    weeklyModel,
    createWeeklySaveParams({
      ...report,
      reviewItems: report?.reviewItems,
      planItems: report?.planItems,
      travelSegments: report?.travelSegments
    })
  );
  patchPeriod(weeklyModel);
}

function patchMonthly(report?: Partial<Api.WorkReport.Monthly.MonthlyReport>) {
  Object.assign(
    monthlyModel,
    createMonthlySaveParams({
      ...report,
      reviewItems: report?.reviewItems,
      planItems: report?.planItems
    })
  );
  patchPeriod(monthlyModel);
}

function patchProject(report?: Partial<Api.WorkReport.Project.ProjectReport>) {
  Object.assign(
    projectModel,
    createProjectSaveParams({
      ...report,
      projectId: report?.projectId || props.initialProjectId,
      flag: report?.flag ?? props.initialFlag,
      currentItems: report?.currentItems,
      nextItems: report?.nextItems
    })
  );
  patchPeriod(projectModel);
}

function applyWeeklyEditableFields(draft: Api.WorkReport.Weekly.WeeklyReport) {
  weeklyModel.reviewItems = normalizeReviewItems(draft.reviewItems);
  weeklyModel.planItems = normalizePlanItems(draft.planItems);
  weeklyModel.travelSegments = draft.travelSegments || [];
}

function applyMonthlyEditableFields(draft: Api.WorkReport.Monthly.MonthlyReport) {
  monthlyModel.reviewItems = normalizeReviewItems(draft.reviewItems);
  monthlyModel.planItems = normalizePlanItems(draft.planItems);
}

function applyProjectEditableFields(draft: Api.WorkReport.Project.ProjectReport) {
  projectModel.projectStatusDesc = draft.projectStatusDesc || '';
  projectModel.projectProgressPlan = draft.projectProgressPlan || '';
  projectModel.projectKeyPoints = draft.projectKeyPoints || '';
  projectModel.projectProblems = draft.projectProblems || '';
  projectModel.currentItems = normalizeProjectItems(draft.currentItems);
  projectModel.nextItems = normalizeProjectItems(draft.nextItems);
}

function applyEditableFieldsByReportType(
  draft:
    | Api.WorkReport.Weekly.WeeklyReport
    | Api.WorkReport.Monthly.MonthlyReport
    | Api.WorkReport.Project.ProjectReport
) {
  if (props.reportType === 'weekly') {
    applyWeeklyEditableFields(draft as Api.WorkReport.Weekly.WeeklyReport);
    return;
  }

  if (props.reportType === 'monthly') {
    applyMonthlyEditableFields(draft as Api.WorkReport.Monthly.MonthlyReport);
    return;
  }

  applyProjectEditableFields(draft as Api.WorkReport.Project.ProjectReport);
}

function createCurrentPeriodPayload(): PeriodPayload {
  return {
    periodKey: activeModel.value.periodKey,
    periodLabel: activeModel.value.periodLabel,
    periodStartDate: activeModel.value.periodStartDate,
    periodEndDate: activeModel.value.periodEndDate
  };
}

async function confirmDraftOverwrite(confirmOverwrite: boolean) {
  if (!confirmOverwrite || props.operateType === 'edit') return true;

  try {
    await ElMessageBox.confirm('重新拉取默认稿会覆盖当前已编辑内容，是否继续？', '覆盖确认', {
      type: 'warning',
      confirmButtonText: '继续',
      cancelButtonText: '取消'
    });
    return true;
  } catch {
    return false;
  }
}

async function fetchEditDraftRefresh() {
  if (props.reportType === 'weekly') {
    return fetchRefreshWeeklyReportDraft(weeklyModel);
  }

  if (props.reportType === 'monthly') {
    return fetchRefreshMonthlyReportDraft(monthlyModel);
  }

  return fetchRefreshProjectReportDraft(projectModel.projectId, {
    periodKey: projectModel.periodKey,
    periodLabel: projectModel.periodLabel,
    periodStartDate: projectModel.periodStartDate,
    periodEndDate: projectModel.periodEndDate,
    flag: projectModel.flag,
    projectStatusDesc: projectModel.projectStatusDesc,
    projectProgressPlan: projectModel.projectProgressPlan,
    projectKeyPoints: projectModel.projectKeyPoints,
    projectProblems: projectModel.projectProblems,
    currentItems: projectModel.currentItems,
    nextItems: projectModel.nextItems
  });
}

async function fetchDefaultDraftPreview() {
  const period = createCurrentPeriodPayload();

  if (props.reportType === 'weekly') {
    return fetchPreviewWeeklyReportDefaultDraft(period);
  }

  if (props.reportType === 'monthly') {
    return fetchPreviewMonthlyReportDefaultDraft(period);
  }

  return fetchPreviewProjectReportDefaultDraft(projectModel.projectId, {
    ...period,
    flag: projectModel.flag
  });
}

async function loadDetail() {
  if (!props.rowData?.id) return;

  loading.value = true;
  let result;

  if (props.reportType === 'weekly') {
    result = await fetchGetWeeklyReportDetail(props.rowData.id);
  } else if (props.reportType === 'monthly') {
    result = await fetchGetMonthlyReportDetail(props.rowData.id);
  } else {
    result = await fetchGetProjectReportDetail(props.rowData.id);
  }
  loading.value = false;

  if (result.error || !result.data) return;

  baseInfo.value = result.data;

  if (props.reportType === 'weekly') patchWeekly(result.data as Api.WorkReport.Weekly.WeeklyReport);
  if (props.reportType === 'monthly') patchMonthly(result.data as Api.WorkReport.Monthly.MonthlyReport);
  if (props.reportType === 'project') patchProject(result.data as Api.WorkReport.Project.ProjectReport);
}

async function loadInitAndDraft() {
  loading.value = true;
  let initResult;

  if (props.reportType === 'weekly') {
    initResult = await fetchInitWeeklyReport();
  } else if (props.reportType === 'monthly') {
    initResult = await fetchInitMonthlyReport();
  } else {
    initResult = await fetchInitProjectReport(props.initialProjectId);
  }

  if (!initResult.error && initResult.data) {
    baseInfo.value = initResult.data;
    if (props.reportType === 'weekly') patchWeekly(initResult.data as Api.WorkReport.Weekly.WeeklyReport);
    if (props.reportType === 'monthly') patchMonthly(initResult.data as Api.WorkReport.Monthly.MonthlyReport);
    if (props.reportType === 'project') patchProject(initResult.data as Api.WorkReport.Project.ProjectReport);
  }

  await pullDefaultDraft(false);
  loading.value = false;
}

async function pullDefaultDraft(confirmOverwrite = true) {
  const confirmed = await confirmDraftOverwrite(confirmOverwrite);
  if (!confirmed) return;

  if (props.operateType === 'edit') {
    const refreshResult = await fetchEditDraftRefresh();

    if (refreshResult.error || !refreshResult.data) return;

    applyEditableFieldsByReportType(refreshResult.data);

    window.$message?.success('最新数据已刷新');
    return;
  }

  const result = await fetchDefaultDraftPreview();

  if (result.error || !result.data) return;

  applyEditableFieldsByReportType(result.data);
}

watch(visible, isVisible => {
  if (!isVisible) return;
  baseInfo.value = null;
  if (props.operateType === 'edit') {
    loadDetail();
  } else {
    loadInitAndDraft();
  }
});

function addReviewItem(items: Api.WorkReport.Common.PersonalReportReviewItem[]) {
  items.push(createBlankReviewItem(items.length));
}

function addPlanItem(items: Api.WorkReport.Common.PersonalReportPlanItem[]) {
  items.push(createBlankPlanItem(items.length));
}

function addProjectItem(items: Api.WorkReport.Project.ProjectReportItem[]) {
  items.push(createBlankProjectItem());
}

function removeItem<T>(items: T[], index: number) {
  if (items.length <= 1) return;
  items.splice(index, 1);
}

function validateBase() {
  if (!activeModel.value.periodKey || !activeModel.value.periodStartDate || !activeModel.value.periodEndDate) {
    window.$message?.warning('请先选择报告周期');
    return false;
  }

  if (props.reportType === 'project' && !projectModel.projectId) {
    window.$message?.warning('请选择项目');
    return false;
  }

  return true;
}

async function handleSubmit() {
  if (!validateBase()) return;

  submitting.value = true;
  let result;

  if (props.reportType === 'weekly') {
    result =
      props.operateType === 'add'
        ? await fetchCreateWeeklyReport(weeklyModel)
        : await fetchUpdateWeeklyReport(props.rowData!.id, weeklyModel);
  } else if (props.reportType === 'monthly') {
    result =
      props.operateType === 'add'
        ? await fetchCreateMonthlyReport(monthlyModel)
        : await fetchUpdateMonthlyReport(props.rowData!.id, monthlyModel);
  } else {
    result =
      props.operateType === 'add'
        ? await fetchCreateProjectReport(projectModel)
        : await fetchUpdateProjectReport(props.rowData!.id, projectModel);
  }
  submitting.value = false;

  if (result.error) return;

  window.$message?.success(props.operateType === 'add' ? '工作报告已创建' : '工作报告已保存');
  visible.value = false;
  emit('submitted');
}
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    :title="title"
    :preset="dialogPreset"
    :loading="loading"
    :confirm-loading="submitting"
    max-body-height="76vh"
    @confirm="handleSubmit"
  >
    <div class="work-report-operate">
      <BusinessFormSection title="基础信息">
        <ElDescriptions :column="3" border size="small">
          <ElDescriptionsItem label="填报人">
            {{ baseReporterName }}
          </ElDescriptionsItem>
          <ElDescriptionsItem label="部门">{{ baseDeptName }}</ElDescriptionsItem>
          <ElDescriptionsItem label="岗位">{{ basePostName }}</ElDescriptionsItem>
          <ElDescriptionsItem label="直属上级">{{ baseInfo?.supervisorName || '--' }}</ElDescriptionsItem>
          <ElDescriptionsItem label="周期" :span="2">{{ activeModel.periodLabel || '--' }}</ElDescriptionsItem>
        </ElDescriptions>

        <div class="mt-12px flex justify-end">
          <ElButton plain type="primary" @click="pullDefaultDraft(true)">
            <template #icon>
              <icon-mdi-refresh class="text-icon" />
            </template>
            刷新
          </ElButton>
        </div>
      </BusinessFormSection>

      <template v-if="reportType === 'project'">
        <BusinessFormSection title="项目状况">
          <ElRow :gutter="16">
            <ElCol :span="12">
              <ElFormItem label="项目状态">
                <ElInput v-model="projectModel.projectStatusDesc" type="textarea" :rows="3" />
              </ElFormItem>
            </ElCol>
            <ElCol :span="12">
              <ElFormItem label="整体计划进度">
                <ElInput v-model="projectModel.projectProgressPlan" type="textarea" :rows="3" />
              </ElFormItem>
            </ElCol>
            <ElCol :span="12">
              <ElFormItem label="要点描述">
                <ElInput v-model="projectModel.projectKeyPoints" type="textarea" :rows="3" />
              </ElFormItem>
            </ElCol>
            <ElCol :span="12">
              <ElFormItem label="项目问题">
                <ElInput v-model="projectModel.projectProblems" type="textarea" :rows="3" />
              </ElFormItem>
            </ElCol>
          </ElRow>
        </BusinessFormSection>

        <BusinessFormSection title="本期工作内容">
          <div class="work-report-operate__items">
            <div v-for="(item, index) in projectModel.currentItems" :key="index" class="work-report-operate__item">
              <ElInput v-model="item.itemTitle" placeholder="工作内容" />
              <ElInputNumber v-model="item.workHours" :min="0" :precision="1" placeholder="工时" />
              <ElInput v-model="item.priorityCode" placeholder="优先级" />
              <ElInputNumber v-model="item.progressRate" :min="0" :max="100" :precision="0" placeholder="进度" />
              <ElButton link type="danger" @click="removeItem(projectModel.currentItems, index)">删除</ElButton>
            </div>
            <ElButton plain @click="addProjectItem(projectModel.currentItems)">新增本期工作</ElButton>
          </div>
        </BusinessFormSection>

        <BusinessFormSection title="下期计划工作内容">
          <div class="work-report-operate__items">
            <div v-for="(item, index) in projectModel.nextItems" :key="index" class="work-report-operate__item">
              <ElInput v-model="item.itemTitle" placeholder="工作内容" />
              <ElInputNumber v-model="item.workHours" :min="0" :precision="1" placeholder="工时" />
              <ElInput v-model="item.priorityCode" placeholder="优先级" />
              <ElInputNumber v-model="item.progressRate" :min="0" :max="100" :precision="0" placeholder="进度" />
              <ElButton link type="danger" @click="removeItem(projectModel.nextItems, index)">删除</ElButton>
            </div>
            <ElButton plain @click="addProjectItem(projectModel.nextItems)">新增下期工作</ElButton>
          </div>
        </BusinessFormSection>
      </template>

      <template v-else>
        <BusinessFormSection title="当期重点工作回顾">
          <div class="work-report-operate__cards">
            <div
              v-for="(item, index) in reportType === 'weekly' ? weeklyModel.reviewItems : monthlyModel.reviewItems"
              :key="index"
              class="work-report-operate__card"
            >
              <ElRow :gutter="16">
                <ElCol :span="14">
                  <ElFormItem label="事项标题">
                    <ElInput v-model="item.itemTitle" />
                  </ElFormItem>
                </ElCol>
                <ElCol :span="6">
                  <ElFormItem label="工时">
                    <ElInputNumber v-model="item.workHours" class="w-full" :min="0" :precision="1" />
                  </ElFormItem>
                </ElCol>
                <ElCol :span="4" class="flex items-end justify-end pb-16px">
                  <ElButton
                    link
                    type="danger"
                    @click="
                      removeItem(reportType === 'weekly' ? weeklyModel.reviewItems : monthlyModel.reviewItems, index)
                    "
                  >
                    删除
                  </ElButton>
                </ElCol>
                <ElCol :span="12">
                  <ElFormItem label="工作内容">
                    <ElInput v-model="item.contentText" type="textarea" :rows="3" />
                  </ElFormItem>
                </ElCol>
                <ElCol :span="12">
                  <ElFormItem label="复盘反思">
                    <ElInput v-model="item.reflectionText" type="textarea" :rows="3" />
                  </ElFormItem>
                </ElCol>
              </ElRow>
            </div>
            <ElButton
              plain
              @click="addReviewItem(reportType === 'weekly' ? weeklyModel.reviewItems : monthlyModel.reviewItems)"
            >
              新增回顾项
            </ElButton>
          </div>
        </BusinessFormSection>

        <BusinessFormSection title="下周期重点工作计划">
          <div class="work-report-operate__cards">
            <div
              v-for="(item, index) in reportType === 'weekly' ? weeklyModel.planItems : monthlyModel.planItems"
              :key="index"
              class="work-report-operate__card"
            >
              <ElRow :gutter="16">
                <ElCol :span="20">
                  <ElFormItem label="计划标题">
                    <ElInput v-model="item.itemTitle" />
                  </ElFormItem>
                </ElCol>
                <ElCol :span="4" class="flex items-end justify-end pb-16px">
                  <ElButton
                    link
                    type="danger"
                    @click="removeItem(reportType === 'weekly' ? weeklyModel.planItems : monthlyModel.planItems, index)"
                  >
                    删除
                  </ElButton>
                </ElCol>
                <ElCol :span="12">
                  <ElFormItem label="目标">
                    <ElInput v-model="item.targetText" type="textarea" :rows="3" />
                  </ElFormItem>
                </ElCol>
                <ElCol :span="12">
                  <ElFormItem label="支持需求">
                    <ElInput v-model="item.supportNeed" type="textarea" :rows="3" />
                  </ElFormItem>
                </ElCol>
              </ElRow>
            </div>
            <ElButton
              plain
              @click="addPlanItem(reportType === 'weekly' ? weeklyModel.planItems : monthlyModel.planItems)"
            >
              新增计划项
            </ElButton>
          </div>
        </BusinessFormSection>

        <BusinessFormSection v-if="reportType === 'weekly'" title="出差信息">
          <ElFormItem label="是否出差">
            <ElSwitch v-model="weeklyModel.isBusinessTrip" />
          </ElFormItem>
          <div v-if="weeklyModel.isBusinessTrip" class="work-report-operate__items">
            <div v-for="(item, index) in weeklyModel.travelSegments" :key="index" class="work-report-operate__item">
              <ElDatePicker v-model="item.startDate" type="date" value-format="YYYY-MM-DD" placeholder="开始日期" />
              <ElDatePicker v-model="item.endDate" type="date" value-format="YYYY-MM-DD" placeholder="结束日期" />
              <ElInputNumber v-model="item.travelDays" :min="0" :precision="1" placeholder="天数" />
              <ElInput v-model="item.location" placeholder="地点" />
              <ElButton link type="danger" @click="removeItem(weeklyModel.travelSegments, index)">删除</ElButton>
            </div>
            <ElButton
              plain
              @click="
                weeklyModel.travelSegments.push({
                  sort: weeklyModel.travelSegments.length + 1,
                  travelDays: 0,
                  location: ''
                })
              "
            >
              新增出差分段
            </ElButton>
          </div>
        </BusinessFormSection>
      </template>
    </div>
  </BusinessFormDialog>
</template>

<style scoped>
.work-report-operate {
  min-width: 0;
}

.work-report-operate__cards,
.work-report-operate__items {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.work-report-operate__card,
.work-report-operate__item {
  padding: 12px;
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
  background-color: var(--el-fill-color-extra-light);
}

.work-report-operate__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px 120px 120px auto;
  gap: 10px;
  align-items: center;
}

@media (width <= 900px) {
  .work-report-operate__item {
    grid-template-columns: 1fr;
  }
}
</style>
