<template>
  <ContentWrap>
    <el-form
      ref="queryFormRef"
      :inline="true"
      :model="queryParams"
      class="-mb-15px"
      label-width="88px"
    >
      <el-form-item label="工程名称" prop="projectName">
        <el-input
          v-model="queryParams.projectName"
          class="!w-240px"
          clearable
          placeholder="请输入工程名称"
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="开始年度" prop="projectStartYear">
        <el-date-picker
          v-model="queryProjectStartYearValue"
          class="!w-180px"
          clearable
          placeholder="请选择年度"
          type="year"
          value-format="YYYY"
        />
      </el-form-item>
      <el-form-item>
        <el-button @click="handleQuery">
          <Icon class="mr-5px" icon="ep:search" />
          搜索
        </el-button>
        <el-button @click="resetQuery">
          <Icon class="mr-5px" icon="ep:refresh" />
          重置
        </el-button>
      </el-form-item>
    </el-form>
  </ContentWrap>

  <ContentWrap>
    <el-table
      ref="projectTableRef"
      v-loading="loading"
      :data="projectList"
      highlight-current-row
      @current-change="handleCurrentProjectChange"
    >
      <el-table-column align="center" label="项目ID" prop="id" width="88" />
      <el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
      <el-table-column align="center" label="项目负责人" min-width="180">
        <template #default="scope">
          {{ getProjectLeadText(scope.row.projectManagerName, scope.row.engineeringPrincipalName) }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
    </el-table>
    <Pagination
      v-model:limit="queryParams.pageSize"
      v-model:page="queryParams.pageNo"
      :total="total"
      @pagination="getProjectList"
    />
  </ContentWrap>

  <el-row :gutter="16">
    <el-col :span="8">
      <ContentWrap>
        <div class="mb-12px text-14px font-600">
          {{ currentProject?.projectName || '合约规划列表' }}
        </div>
        <el-table
          ref="planningTableRef"
          v-loading="planningLoading"
          :data="planningList"
          highlight-current-row
          @current-change="handleCurrentPlanningChange"
        >
          <el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
          <el-table-column align="center" label="归属类型" min-width="110">
            <template #default="scope">
              {{ getOwnershipTypeLabel(scope.row.ownershipType) }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="开始年度" prop="planningStartYear" width="100" />
          <el-table-column align="center" label="考核产值(元)" width="120">
            <template #default="scope">
              {{ formatAmountText(scope.row.assessmentOutputValue) }}
            </template>
          </el-table-column>
        </el-table>
      </ContentWrap>
    </el-col>

    <el-col :span="16">
      <ContentWrap v-if="currentPlanning && formData">
        <div class="mb-16px flex items-center justify-between gap-16px">
          <div>
            <div class="text-16px font-600">{{ currentPlanning.planningContent }}</div>
            <div class="mt-4px text-13px text-[var(--el-text-color-secondary)]">
              年度：{{ formData.year || '-' }}，考核产值：{{ formatAmountText(formData.assessmentOutputValue) }} 元
            </div>
          </div>
          <div class="flex items-center gap-12px">
            <el-button
              v-hasPermi="['tjt:output-split:update']"
              plain
              type="primary"
              @click="openEditDialog"
            >
              <Icon class="mr-5px" icon="ep:edit" />
              编辑比例
            </el-button>
          </div>
        </div>

        <el-descriptions :column="2" border title="基础信息">
          <el-descriptions-item label="项目名称">{{ formData.projectName || '-' }}</el-descriptions-item>
          <el-descriptions-item label="规划内容">{{ formData.planningContent || '-' }}</el-descriptions-item>
          <el-descriptions-item label="项目负责人">
            {{ getProjectLeadText(formData.projectManagerName, formData.engineeringLeaderName) }}
          </el-descriptions-item>
        </el-descriptions>

        <el-divider content-position="left">项目层结果</el-divider>
        <el-table :data="projectResultRows" border>
          <el-table-column align="center" label="类别" min-width="160" prop="label" />
          <el-table-column align="center" label="比例" min-width="120">
            <template #default="scope">
              {{ scope.row.percentText }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="金额(元)" min-width="140">
            <template #default="scope">
              {{ formatAmountText(scope.row.amount) }}
            </template>
          </el-table-column>
        </el-table>

        <el-divider content-position="left">专业层结果</el-divider>
        <el-table :data="specialtyResultRows" border>
          <el-table-column align="center" label="专业" min-width="140" prop="label" />
          <el-table-column align="center" label="比例" min-width="120">
            <template #default="scope">
              {{ scope.row.percentText }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="金额(元)" min-width="140">
            <template #default="scope">
              {{ formatAmountText(scope.row.amount) }}
            </template>
          </el-table-column>
        </el-table>

        <el-divider content-position="left">年度分配信息</el-divider>
        <div class="mb-12px">
          <el-radio-group v-model="selectedAnnualCategory" size="small">
            <el-radio-button
              v-for="item in annualCategoryOptions"
              :key="item.value"
              :label="item.value"
            >
              {{ item.label }}
            </el-radio-button>
          </el-radio-group>
        </div>
        <el-row :gutter="16" class="mb-16px">
          <el-col v-for="item in annualSummaryCards" :key="item.label" :span="8">
            <div class="rounded-8px bg-[var(--el-fill-color-light)] px-16px py-12px">
              <div class="text-12px text-[var(--el-text-color-secondary)]">{{ item.label }}</div>
              <div class="mt-6px text-18px font-600">{{ formatAmountText(item.amount) }}</div>
            </div>
          </el-col>
        </el-row>
        <el-table v-loading="quarterLoading" :data="annualDistributionRows" border>
          <el-table-column align="center" label="分配年度" min-width="120" prop="distributionYear" />
          <el-table-column
            v-for="quarter in QUARTER_OPTIONS"
            :key="String(quarter.value)"
            align="center"
            :label="quarter.label"
            min-width="150"
          >
            <template #default="scope">
              {{ formatAmountText(scope.row.quarterAmounts[Number(quarter.value)]) }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="年度合计(元)" min-width="160">
            <template #default="scope">
              {{ formatAmountText(scope.row.yearTotal) }}
            </template>
          </el-table-column>
        </el-table>
      </ContentWrap>

      <ContentWrap v-else>
        <el-empty description="请选择合约规划后查看分配结果" />
      </ContentWrap>
    </el-col>
  </el-row>

  <Dialog v-model="dialogVisible" title="编辑专业及项目总分配比例" width="920">
    <template v-if="editForm">
      <el-divider content-position="left">项目层比例编辑</el-divider>
      <el-row :gutter="16">
        <el-col v-for="item in editProjectRatioItems" :key="item.key" :span="12">
          <div class="ratio-card">
            <div class="ratio-title">{{ item.label }}</div>
            <el-input-number
              :model-value="item.percent"
              :disabled="item.key === 'officeRatio'"
              :min="0"
              :precision="2"
              :step="0.1"
              class="!w-1/1"
              controls-position="right"
              @update:model-value="(value) => updateProjectRatio(item.key, value)"
            />
            <div class="ratio-amount">金额：{{ formatAmountText(item.amount) }} 元</div>
          </div>
        </el-col>
      </el-row>
      <div class="mt-8px text-12px" :class="projectRatioTotalClass">
        项目层比例合计：{{ projectRatioTotalText }}
      </div>

      <el-divider content-position="left">专业层比例编辑</el-divider>
      <el-row :gutter="16">
        <el-col v-for="item in editSpecialtyRatioItems" :key="item.key" :span="8" class="mb-12px">
          <div class="ratio-card">
            <div class="ratio-title">{{ item.label }}</div>
            <el-input-number
              :model-value="item.percent"
              :disabled="item.key === 'archRatio'"
              :min="0"
              :precision="2"
              :step="0.1"
              class="!w-1/1"
              controls-position="right"
              @update:model-value="(value) => updateSpecialtyRatio(item.key, value)"
            />
            <div class="ratio-amount">金额：{{ formatAmountText(item.amount) }} 元</div>
          </div>
        </el-col>
      </el-row>
      <div class="mt-8px text-12px" :class="specialtyRatioTotalClass">
        专业层比例合计：{{ specialtyRatioTotalText }}
      </div>
    </template>

    <template #footer>
      <el-button :loading="saveLoading" type="primary" @click="handleSave">保存</el-button>
      <el-button @click="dialogVisible = false">取消</el-button>
    </template>
  </Dialog>
</template>

<script lang="ts" setup>
import * as ProjectApi from '@/api/tjt/project'
import * as PlanningApi from '@/api/tjt/planning'
import * as PlanningQuarterApi from '@/api/tjt/planningQuarter'
import * as OutputSplitApi from '@/api/tjt/outputSplit'
import {
  formatAmountText,
  fromPercentValue,
  getOwnershipTypeLabel,
  OUTPUT_SPLIT_SPECIALTY_OPTIONS,
  QUARTER_OPTIONS,
  toPercentValue
} from '@/views/tjt/shared/planning'

defineOptions({ name: 'TjtOutputSplit' })

type AnnualCategoryKey =
  | 'project_lead'
  | 'arch'
  | 'decor'
  | 'struct'
  | 'water'
  | 'elec'
  | 'hvac'
  | 'digital'

interface QuarterYearRow {
  distributionYear: number
  quarters: PlanningQuarterApi.ProjectPlanningQuarterVO[]
}

const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
  { label: '项目经理/项目负责人', value: 'project_lead' },
  { label: '建筑专业', value: 'arch' },
  { label: '装修专业', value: 'decor' },
  { label: '结构专业', value: 'struct' },
  { label: '水专业', value: 'water' },
  { label: '电气专业', value: 'elec' },
  { label: '暖通专业', value: 'hvac' },
  { label: '数字化设计专业', value: 'digital' }
]

const message = useMessage()

const loading = ref(false)
const planningLoading = ref(false)
const quarterLoading = ref(false)
const saveLoading = ref(false)
const total = ref(0)
const projectList = ref<ProjectApi.ProjectVO[]>([])
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
const currentProject = ref<ProjectApi.ProjectVO>()
const currentPlanning = ref<PlanningApi.ProjectPlanningVO>()
const formData = ref<OutputSplitApi.ProjectOutputSplitVO>()
const editForm = ref<OutputSplitApi.ProjectOutputSplitVO>()
const quarterRows = ref<QuarterYearRow[]>([])
const selectedAnnualCategory = ref<AnnualCategoryKey>('project_lead')
const dialogVisible = ref(false)
const queryFormRef = ref()
const projectTableRef = ref()
const planningTableRef = ref()

const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
  pageNo: 1,
  pageSize: 10,
  projectName: undefined,
  projectStartYear: undefined
})

const queryProjectStartYearValue = computed({
  get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
  set: (value?: string) => {
    queryParams.projectStartYear = value ? Number(value) : undefined
  }
})

const toNumeric = (value?: number | string | null) => {
  const numericValue = Number(value ?? 0)
  return Number.isNaN(numericValue) ? 0 : numericValue
}

const multiplyAmount = (...values: Array<number | string | null | undefined>) => {
  let result = 1
  values.forEach((value) => {
    result *= toNumeric(value)
  })
  return Number(result.toFixed(2))
}

const formatRatioText = (value?: number | string | null) => `${(toPercentValue(value) ?? 0).toFixed(2)}%`

const getRatioValue = (model: OutputSplitApi.ProjectOutputSplitVO, key: string) =>
  (model as unknown as Record<string, number | undefined>)[key]

const getProjectLeadText = (projectManagerName?: string, engineeringLeaderName?: string) =>
  [projectManagerName, engineeringLeaderName].filter(Boolean).join(' / ') || '-'

const buildProjectRows = (model?: OutputSplitApi.ProjectOutputSplitVO) => {
  if (!model) {
    return []
  }
  return [
    {
      key: 'projectLeadRatio',
      label: '项目经理/项目负责人',
      percentText: formatRatioText(model.projectLeadRatio),
      percent: toPercentValue(model.projectLeadRatio),
      amount: model.projectLeadAmount
    },
    {
      key: 'officeRatio',
      label: '专业所',
      percentText: formatRatioText(model.officeRatio),
      percent: toPercentValue(model.officeRatio),
      amount: model.officeAmount
    }
  ]
}

const buildSpecialtyRows = (model?: OutputSplitApi.ProjectOutputSplitVO) => {
  if (!model) {
    return []
  }
  const amountMap: Record<string, number | undefined> = {
    arch: model.archAmount,
    decor: model.decorAmount,
    struct: model.structAmount,
    water: model.waterAmount,
    elec: model.elecAmount,
    hvac: model.hvacAmount,
    digital: model.digitalAmount
  }
  return OUTPUT_SPLIT_SPECIALTY_OPTIONS.map((item) => ({
    key: `${item.value}Ratio`,
    label: item.label,
    percentText: formatRatioText(getRatioValue(model, `${item.value}Ratio`)),
    percent: toPercentValue(getRatioValue(model, `${item.value}Ratio`)),
    amount: amountMap[item.value]
  }))
}

const projectResultRows = computed(() => buildProjectRows(formData.value))
const specialtyResultRows = computed(() => buildSpecialtyRows(formData.value))
const editProjectRatioItems = computed(() => buildProjectRows(editForm.value))
const editSpecialtyRatioItems = computed(() => buildSpecialtyRows(editForm.value))

const annualCategoryMeta = computed(() => {
  const model = formData.value
  const option = annualCategoryOptions.find((item) => item.value === selectedAnnualCategory.value)
  if (!model || !option) {
    return { label: '-', ratio: 0, totalAmount: 0 }
  }
  if (selectedAnnualCategory.value === 'project_lead') {
    const ratio = Number(toNumeric(model.projectLeadRatio).toFixed(4))
    return {
      label: option.label,
      ratio,
      totalAmount: multiplyAmount(model.assessmentOutputValue, ratio)
    }
  }
  const specialtyRatio = toNumeric(getRatioValue(model, `${selectedAnnualCategory.value}Ratio`))
  const ratio = Number((toNumeric(model.officeRatio) * specialtyRatio).toFixed(4))
  return {
    label: option.label,
    ratio,
    totalAmount: multiplyAmount(model.assessmentOutputValue, ratio)
  }
})

const annualDistributionRows = computed(() =>
  quarterRows.value.map((row) => {
    const quarterAmounts: Record<number, number> = {}
    let yearTotal = 0
    QUARTER_OPTIONS.forEach((quarter) => {
      const quarterNo = Number(quarter.value)
      const quarterAmount = multiplyAmount(
        row.quarters.find((item) => item.quarterNo === quarterNo)?.distributionAmount,
        annualCategoryMeta.value.ratio
      )
      quarterAmounts[quarterNo] = quarterAmount
      yearTotal += quarterAmount
    })
    return {
      distributionYear: row.distributionYear,
      quarterAmounts,
      yearTotal: Number(yearTotal.toFixed(2))
    }
  })
)

const annualSummaryCards = computed(() => [
  {
    label: '总分配',
    amount: multiplyAmount(
      currentPlanning.value?.assessmentOutputValue,
      currentPlanning.value?.totalDistributionAmount,
      annualCategoryMeta.value.ratio
    )
  },
  {
    label: '已分配',
    amount: multiplyAmount(
      currentPlanning.value?.assessmentOutputValue,
      currentPlanning.value?.allocatedAmount,
      annualCategoryMeta.value.ratio
    )
  },
  {
    label: '待分配',
    amount: multiplyAmount(
      currentPlanning.value?.assessmentOutputValue,
      currentPlanning.value?.pendingAmount,
      annualCategoryMeta.value.ratio
    )
  }
])

const projectRatioTotal = computed(() =>
  editProjectRatioItems.value.reduce((sum, item) => sum + Number(item.percent || 0), 0)
)
const specialtyRatioTotal = computed(() =>
  editSpecialtyRatioItems.value.reduce((sum, item) => sum + Number(item.percent || 0), 0)
)
const projectRatioTotalText = computed(() => `${projectRatioTotal.value.toFixed(2)}%`)
const specialtyRatioTotalText = computed(() => `${specialtyRatioTotal.value.toFixed(2)}%`)
const projectRatioTotalClass = computed(() =>
  Math.abs(projectRatioTotal.value - 100) < 0.001
    ? 'text-[var(--el-color-success)]'
    : 'text-[var(--el-color-danger)]'
)
const specialtyRatioTotalClass = computed(() =>
  Math.abs(specialtyRatioTotal.value - 100) < 0.001
    ? 'text-[var(--el-color-success)]'
    : 'text-[var(--el-color-danger)]'
)

const recalculateOfficeRatio = () => {
  if (!editForm.value) {
    return
  }
  editForm.value.officeRatio = Number(Math.max(0, 1 - Number(editForm.value.projectLeadRatio || 0)).toFixed(4))
}

const recalculateArchRatio = () => {
  if (!editForm.value) {
    return
  }
  const otherSpecialtyTotal =
    Number(editForm.value.decorRatio || 0) +
    Number(editForm.value.structRatio || 0) +
    Number(editForm.value.waterRatio || 0) +
    Number(editForm.value.elecRatio || 0) +
    Number(editForm.value.hvacRatio || 0) +
    Number(editForm.value.digitalRatio || 0)
  editForm.value.archRatio = Number(Math.max(0, 1 - otherSpecialtyTotal).toFixed(4))
}

const buildQuarterRows = (
  planning: PlanningApi.ProjectPlanningVO,
  quarters: PlanningQuarterApi.ProjectPlanningQuarterVO[]
) => {
  const yearSet = new Set<number>()
  if (planning.planningStartYear) {
    yearSet.add(planning.planningStartYear)
  }
  quarters.forEach((item) => yearSet.add(item.distributionYear))
  if (yearSet.size === 0) {
    yearSet.add(new Date().getFullYear())
  }
  return Array.from(yearSet)
    .sort((a, b) => a - b)
    .map((distributionYear) => ({
      distributionYear,
      quarters: QUARTER_OPTIONS.map((option) => {
        const quarterNo = Number(option.value)
        const match = quarters.find(
          (item) =>
            item.distributionYear === distributionYear && Number(item.quarterNo) === quarterNo
        )
        return (
          match || {
            planningId: planning.id!,
            distributionYear,
            quarterNo,
            distributionRatio: undefined,
            distributionAmount: 0
          }
        )
      })
    }))
}

const getProjectList = async () => {
  loading.value = true
  try {
    const data = await ProjectApi.getProjectPage(queryParams)
    projectList.value = data.list
    total.value = data.total
    if (!projectList.value.length) {
      currentProject.value = undefined
      planningList.value = []
      currentPlanning.value = undefined
      formData.value = undefined
      quarterRows.value = []
      return
    }
    const targetProjectId = currentProject.value?.id || projectList.value[0].id
    const targetProject =
      projectList.value.find((item) => item.id === targetProjectId) || projectList.value[0]
    await nextTick()
    projectTableRef.value?.setCurrentRow(targetProject)
  } finally {
    loading.value = false
  }
}

const getPlanningList = async () => {
  if (!currentProject.value?.id) {
    planningList.value = []
    currentPlanning.value = undefined
    formData.value = undefined
    quarterRows.value = []
    return
  }
  planningLoading.value = true
  try {
    const list = await PlanningApi.getProjectPlanningListByProjectId(currentProject.value.id)
    planningList.value = list
    if (!planningList.value.length) {
      currentPlanning.value = undefined
      formData.value = undefined
      quarterRows.value = []
      return
    }
    const targetPlanningId = currentPlanning.value?.id || planningList.value[0].id
    const targetPlanning =
      planningList.value.find((item) => item.id === targetPlanningId) || planningList.value[0]
    await nextTick()
    planningTableRef.value?.setCurrentRow(targetPlanning)
  } finally {
    planningLoading.value = false
  }
}

const loadPlanningRelatedData = async (planning: PlanningApi.ProjectPlanningVO) => {
  if (!planning.id) {
    return
  }
  quarterLoading.value = true
  try {
    const [planningDetail, outputSplit, quarterList] = await Promise.all([
      PlanningApi.getProjectPlanning(planning.id),
      OutputSplitApi.getProjectOutputSplitByPlanningId(planning.id),
      PlanningQuarterApi.getProjectPlanningQuarterListByPlanningId(planning.id)
    ])
    currentPlanning.value = planningDetail
    formData.value = outputSplit
    quarterRows.value = buildQuarterRows(planningDetail, quarterList)
  } finally {
    quarterLoading.value = false
  }
}

const handleQuery = () => {
  queryParams.pageNo = 1
  getProjectList()
}

const resetQuery = () => {
  queryFormRef.value?.resetFields()
  handleQuery()
}

const handleCurrentProjectChange = async (row?: ProjectApi.ProjectVO) => {
  currentProject.value = row || undefined
  await getPlanningList()
}

const handleCurrentPlanningChange = async (row?: PlanningApi.ProjectPlanningVO) => {
  currentPlanning.value = row || undefined
  if (!row?.id) {
    formData.value = undefined
    quarterRows.value = []
    return
  }
  await loadPlanningRelatedData(row)
}

const refreshCurrentPlanning = async () => {
  if (!currentPlanning.value?.id) {
    return
  }
  await loadPlanningRelatedData(currentPlanning.value)
}

const openEditDialog = () => {
  if (!formData.value) {
    return
  }
  editForm.value = { ...formData.value }
  dialogVisible.value = true
}

const updateProjectRatio = (key: string, value?: number) => {
  if (!editForm.value || key === 'officeRatio') {
    return
  }
  ;(editForm.value as unknown as Record<string, number | undefined>)[key] =
    fromPercentValue(value) ?? 0
  recalculateOfficeRatio()
}

const updateSpecialtyRatio = (key: string, value?: number) => {
  if (!editForm.value || key === 'archRatio') {
    return
  }
  ;(editForm.value as unknown as Record<string, number | undefined>)[key] =
    fromPercentValue(value) ?? 0
  recalculateArchRatio()
}

const handleSave = async () => {
  if (!editForm.value) {
    return
  }
  if (Math.abs(projectRatioTotal.value - 100) >= 0.001) {
    message.warning('项目层比例合计必须等于 100%')
    return
  }
  if (Math.abs(specialtyRatioTotal.value - 100) >= 0.001) {
    message.warning('专业层比例合计必须等于 100%')
    return
  }
  saveLoading.value = true
  try {
    await OutputSplitApi.saveProjectOutputSplit({
      planningId: editForm.value.planningId,
      projectLeadRatio: editForm.value.projectLeadRatio,
      officeRatio: editForm.value.officeRatio,
      archRatio: editForm.value.archRatio,
      decorRatio: editForm.value.decorRatio,
      structRatio: editForm.value.structRatio,
      waterRatio: editForm.value.waterRatio,
      elecRatio: editForm.value.elecRatio,
      hvacRatio: editForm.value.hvacRatio,
      digitalRatio: editForm.value.digitalRatio
    })
    message.success('保存成功')
    dialogVisible.value = false
    await refreshCurrentPlanning()
  } finally {
    saveLoading.value = false
  }
}

onMounted(() => {
  getProjectList()
})

onActivated(() => {
  getProjectList()
})
</script>

<style lang="scss" scoped>
.ratio-card {
  padding: 12px;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
}

.ratio-title {
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
}

.ratio-amount {
  margin-top: 8px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}
</style>
