<template>
  <div class="p-2">
    <el-card shadow="never" style="margin-top: 0">
      <approvalButton
        @submitForm="submitForm"
        @approvalVerifyOpen="approvalVerifyOpen"
        @handleApprovalRecord="handleApprovalRecord"
        :buttonLoading="buttonLoading"
        :id="form.accountInstallmentId"
        :status="form.flowStatus"
        :pageType="routeParams.type"
        :mode="false"
      />
    </el-card>

    <el-card shadow="never" style="margin-top: 0">
      <template #header>
        <div class="flex items-center justify-between">
          <div style="text-align: left; font-weight: bold; font-size: 24px">{{ pageTitle }}</div>
          <el-button v-if="canEditDetail" type="primary" :disabled="!canAddDetail" @click="handleAddDetail">
            <el-icon class="mr-1"><Plus /></el-icon>
            新增分款
          </el-button>
        </div>
      </template>

      <el-descriptions :column="3" border>
        <el-descriptions-item label="回款编号">{{ form.installmentCode }}</el-descriptions-item>
        <el-descriptions-item label="客户名称">{{ form.customerName }}</el-descriptions-item>
        <el-descriptions-item label="回款日期">{{ parseTime(form.paymentDate, '{y}-{m}-{d}') }}</el-descriptions-item>
        <el-descriptions-item label="回款金额">
          <span class="font-medium text-blue-600">¥{{ formatMoney(form.paymentAmount) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="已分款金额">
          <span class="font-medium text-orange-600">¥{{ formatMoney(allocatedAmount) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="剩余可分">
          <span :class="remainingAmount < 0 ? 'text-red-600' : 'text-green-600'" class="font-medium">
            ¥{{ formatMoney(remainingAmount) }}
          </span>
        </el-descriptions-item>
        <el-descriptions-item label="客户经理">{{ form.managerNickNames || '-' }}</el-descriptions-item>
        <el-descriptions-item label="流程状态">
          <dict-tag :options="flow_status" :value="form.flowStatus" />
        </el-descriptions-item>
        <el-descriptions-item label="分款进度">
          <dict-tag :options="installment_status" :value="form.installmentStatus" />
        </el-descriptions-item>
        <el-descriptions-item label="备注" :span="3">{{ form.remark || '-' }}</el-descriptions-item>
      </el-descriptions>

      <el-alert
        v-if="remainingAmount !== 0"
        :title="remainingAmount < 0 ? '分款金额超出回款金额' : '分款金额不足回款金额'"
        type="warning"
        :closable="false"
        class="mt-3"
        show-icon
      />

      <el-table v-loading="detailLoading" :data="detailList" border size="small" class="mt-3">
        <el-table-column label="项目编号" align="center" prop="projectCode" width="120" show-overflow-tooltip />
        <el-table-column label="项目名称" align="center" prop="projectName" min-width="140" show-overflow-tooltip />
        <el-table-column label="合同编号" align="center" prop="contractCode" width="120" show-overflow-tooltip />
        <el-table-column label="合同名称" align="center" prop="contractName" min-width="140" show-overflow-tooltip />
        <el-table-column label="分款阶段" align="center" prop="stageName" width="100" />
        <el-table-column label="分款金额" align="center" width="110">
          <template #default="{ row }">
            <span class="font-medium">¥{{ formatMoney(row.detailAmount) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
        <el-table-column v-if="canEditDetail" label="操作" align="center" width="100" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click="handleEditDetail(row)">编辑</el-button>
            <el-button link type="danger" size="small" @click="handleDeleteDetail(row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-empty
        v-if="!detailLoading && !detailList.length"
        :description="canEditDetail ? '暂无分款明细，请点击新增分款添加' : '暂无分款明细'"
        class="mt-3"
      />
    </el-card>

    <ProjectSelectDialog v-model:visible="showProjectDialog" @project-selected="handleProjectSelected" />
    <ContractSelectDialog v-model:visible="showContractDialog" @contract-selected="handleContractSelected" />

    <el-dialog :title="detailDialog.title" v-model="detailDialog.visible" width="560px" append-to-body>
      <el-form ref="detailFormRef" :model="detailForm" :rules="detailRules" label-width="120px">
        <el-form-item label="项目编号">
          <el-input v-model="detailForm.projectCode" disabled />
        </el-form-item>
        <el-form-item label="项目名称">
          <el-input v-model="detailForm.projectName" disabled />
        </el-form-item>
        <el-form-item label="合同编号">
          <el-input v-model="detailForm.contractCode" disabled />
        </el-form-item>
        <el-form-item label="合同名称">
          <el-input v-model="detailForm.contractName" disabled />
        </el-form-item>
        <el-form-item label="合同额">
          <span class="font-medium text-gray-800">{{ contractTotalPriceDisplay }}</span>
        </el-form-item>
        <el-form-item label="分款节点" prop="paymentStageId">
          <div style="display: flex; flex-flow: row nowrap; align-items: center; gap: 12px; width: 100%; min-width: 0; overflow-x: auto">
            <el-select v-model="detailForm.paymentStageId" placeholder="请选择分款节点" style="width: 150px; flex-shrink: 0">
              <el-option v-for="stage in paymentStageList" :key="stage.paymentStageId" :label="stage.stageName" :value="stage.paymentStageId" />
            </el-select>
            <template v-if="detailForm.paymentStageId">
              <span style="white-space: nowrap; flex-shrink: 0">
                回款比例 <span>{{ selectedStagePaymentRatioText }}</span>
              </span>
              <span style="white-space: nowrap; flex-shrink: 0">
                金额 <span>¥{{ formatMoneyOrDash(selectedStageContractShareAmount) }}</span>
              </span>
            </template>
          </div>
        </el-form-item>
        <el-form-item label="分款金额" prop="detailAmount">
          <el-input-number
            v-model="detailForm.detailAmount"
            :precision="2"
            :min="0.01"
            :max="999999999"
            placeholder="请输入分款金额"
            style="width: 100%"
            controls-position="right"
          />
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="detailForm.remark" type="textarea" :rows="2" placeholder="请输入备注" />
        </el-form-item>
        <el-alert
          v-if="formRemainingAmount !== 0"
          :title="formRemainingAmount < 0 ? '分款金额超出回款金额' : '分款金额不足回款金额'"
          :type="formRemainingAmount < 0 ? 'error' : 'warning'"
          :closable="false"
          show-icon
          class="mb-2"
        >
          <template #default>
            <span class="font-medium">
              {{ formRemainingAmount < 0 ? '已超出' : '还差' }} ¥{{ formatMoney(Math.abs(formRemainingAmount)) }}，分款总金额不能超出回款金额
            </span>
          </template>
        </el-alert>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="detailButtonLoading" type="primary" @click="submitDetailForm">确 定</el-button>
          <el-button @click="cancelDetail">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
    <approvalRecord ref="approvalRecordRef" />
  </div>
</template>

<script setup name="FinAccountInstallmentEdit" lang="ts">
import { Plus } from '@element-plus/icons-vue';
import { getFinAccountInstallment } from '@/api/oa/erp/finAccountInstallment';
import {
  addFinAccountInstallmentDetail,
  getErpFinAccountInstallmentDetailList,
  updateFinAccountInstallmentDetail,
  deleteInstallmentDetailByBo
} from '@/api/oa/erp/finAccountInstallmentDetail';
import { FinAccountInstallmentForm } from '@/api/oa/erp/finAccountInstallment/types';
import { FinAccountInstallmentDetailForm, FinAccountInstallmentDetailVO } from '@/api/oa/erp/finAccountInstallmentDetail/types';
import { getErpContractPaymentMethodJoinList } from '@/api/oa/erp/finAccountReceivable';
import ProjectSelectDialog from '@/views/oa/components/ProjectSelectDialog.vue';
import ContractSelectDialog from '@/views/oa/components/ContractSelectDialog.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import { parseTime } from '@/utils/ruoyi';

const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();

const { installment_status, flow_status } = toRefs<any>(proxy?.useDict('installment_status', 'flow_status'));

const routeParams = ref<Record<string, any>>({});
const buttonLoading = ref(false);
const detailLoading = ref(false);
const detailList = ref<FinAccountInstallmentDetailVO[]>([]);

const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();

const taskVariables = ref<Record<string, any>>({});

const initFormData: FinAccountInstallmentForm = {
  accountInstallmentId: undefined,
  installmentCode: undefined,
  customerName: undefined,
  paymentAmount: undefined,
  paymentDate: undefined,
  currency: 'CNY',
  remark: undefined,
  flowStatus: undefined,
  installmentStatus: undefined,
  accountManagerIds: undefined,
  managerUserIds: [],
  managerNickNames: undefined,
};

const form = ref<FinAccountInstallmentForm>({ ...initFormData });

const pageTitle = computed(() => {
  const t = routeParams.value.type;
  if (t === 'view') return '分款 - 查看';
  if (t === 'approval') return '分款审核';
  return '客户分款';
});

/** 仅分款审核页（type=approval，待办审批进入）可维护分款明细 */
const canEditDetail = computed(() => routeParams.value.type === 'approval');

const allocatedAmount = computed(() =>
  Number((detailList.value || []).reduce((sum, item) => sum + Number(item.detailAmount || 0), 0))
);

const remainingAmount = computed(() => Number(form.value.paymentAmount || 0) - allocatedAmount.value);

/** 分款金额与回款金额平衡容差（元） */
const ALLOCATION_AMOUNT_EPS = 0.005;

/** 剩余可分大于 0 时才允许新增分款 */
const canAddDetail = computed(() => canEditDetail.value && remainingAmount.value > ALLOCATION_AMOUNT_EPS);

/** 提交/审批前校验：分款总额须等于回款金额 */
const validateAllocationBeforeSubmit = (): boolean => {
  const remain = remainingAmount.value;
  if (remain < -ALLOCATION_AMOUNT_EPS) {
    proxy?.$modal.msgWarning(`分款金额超出回款金额，已超出 ¥${formatMoney(Math.abs(remain))}，无法提交`);
    return false;
  }
  if (remain > ALLOCATION_AMOUNT_EPS) {
    proxy?.$modal.msgWarning(`分款金额不足回款金额，还差 ¥${formatMoney(remain)} 未分配，无法提交`);
    return false;
  }
  if (!detailList.value.length) {
    proxy?.$modal.msgWarning('请至少添加一条分款明细后再提交');
    return false;
  }
  return true;
};

const formRemainingAmount = computed(() => {
  const currentDetailAmount = Number(detailForm.detailAmount) || 0;
  const existingTotal = Number(
    (detailList.value || []).reduce((sum, item) => {
      if (detailForm.installmentDetailId && item.installmentDetailId === detailForm.installmentDetailId) {
        return sum;
      }
      return sum + Number(item.detailAmount || 0);
    }, 0)
  );
  return Number(form.value.paymentAmount || 0) - existingTotal - currentDetailAmount;
});

const showProjectDialog = ref(false);
const showContractDialog = ref(false);
const selectedProject = ref<any>(null);

interface ContractPaymentStageJoinRow {
  paymentStageId: string | number;
  stageName?: string;
  paymentPercentage?: number | string;
  paymentAmount?: number | string;
}

const paymentStageList = ref<ContractPaymentStageJoinRow[]>([]);
const detailFormContractTotalPrice = ref<number | undefined>(undefined);

const formatMoney = (val: number | string | undefined | null) => {
  if (val === undefined || val === null) return '0.00';
  const n = Number(val || 0);
  return n.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};

const formatMoneyOrDash = (money: number | undefined | null) => {
  if (money === undefined || money === null || Number.isNaN(Number(money))) return '—';
  return formatMoney(money);
};

const contractTotalPriceDisplay = computed(() => {
  const v = detailFormContractTotalPrice.value;
  if (v === undefined || v === null || Number.isNaN(Number(v))) return '—';
  return `¥${formatMoney(v)}`;
});

const selectedPaymentStageRow = computed(() => {
  const id = detailForm.paymentStageId;
  if (id == null || id === '') return null;
  return paymentStageList.value.find((s) => String(s.paymentStageId) === String(id)) ?? null;
});

const selectedStagePaymentRatioText = computed(() => {
  const row = selectedPaymentStageRow.value;
  if (row && row.paymentPercentage !== undefined && row.paymentPercentage !== null && row.paymentPercentage !== '') {
    const n = Number(row.paymentPercentage);
    if (!Number.isNaN(n)) return `${n}%`;
  }
  const p = detailForm.contractPaymentPercentage;
  if (p !== undefined && p !== null && !Number.isNaN(Number(p))) {
    const n = Number(p);
    if (!Number.isNaN(n)) return `${n}%`;
  }
  return '—';
});

const selectedStageContractShareAmount = computed(() => {
  const row = selectedPaymentStageRow.value;
  if (row) {
    const backend = row.paymentAmount !== undefined && row.paymentAmount !== null && row.paymentAmount !== '' ? Number(row.paymentAmount) : NaN;
    if (!Number.isNaN(backend)) return backend;
    const total = Number(detailFormContractTotalPrice.value);
    const pct = Number(row.paymentPercentage);
    if (!Number.isNaN(total) && !Number.isNaN(pct)) return (total * pct) / 100;
  }
  const dAmt = detailForm.contractPaymentAmount;
  if (dAmt !== undefined && dAmt !== null && !Number.isNaN(Number(dAmt))) {
    return Number(dAmt);
  }
  const total = Number(detailFormContractTotalPrice.value);
  const pct = Number(detailForm.contractPaymentPercentage);
  if (!Number.isNaN(total) && !Number.isNaN(pct)) return (total * pct) / 100;
  return undefined;
});

const getPaymentStages = async (contractId: string | number | undefined) => {
  paymentStageList.value = [];
  if (contractId && contractId !== '') {
    const res = await getErpContractPaymentMethodJoinList({ contractId: contractId });
    paymentStageList.value = (res.data || []) as ContractPaymentStageJoinRow[];
  }
};

const detailDialog = reactive({
  visible: false,
  title: '新增分款明细'
});
const detailButtonLoading = ref(false);
const detailFormRef = ref<ElFormInstance>();
const initDetailForm: FinAccountInstallmentDetailForm = {
  installmentDetailId: undefined,
  accountInstallmentId: undefined,
  projectId: undefined,
  projectCode: undefined,
  projectName: undefined,
  contractId: undefined,
  contractCode: undefined,
  contractName: undefined,
  paymentStageId: undefined,
  detailAmount: undefined,
  installmentStatus: undefined,
  remark: undefined,
  contractTotalPrice: undefined,
  contractPaymentPercentage: undefined,
  contractPaymentAmount: undefined
};
const detailForm = reactive<FinAccountInstallmentDetailForm>({ ...initDetailForm });

function validateDetailAmountNotExceedNode(_rule: unknown, value: unknown, callback: (e?: Error) => void) {
  const max = selectedStageContractShareAmount.value;
  if (max == null || Number.isNaN(Number(max))) {
    callback();
    return;
  }
  const maxN = Number(max);
  const v = Number(value);
  if (value === undefined || value === null || value === '' || Number.isNaN(v)) {
    callback();
    return;
  }
  const vCents = Math.round(v * 100);
  const maxCents = Math.round(maxN * 100);
  if (vCents > maxCents) {
    callback(new Error(`分款金额不能大于节点约定金额（¥${formatMoney(maxN)}）`));
    return;
  }
  callback();
}

const detailRules = {
  paymentStageId: [{ required: true, message: '请选择分款节点', trigger: 'change' }],
  detailAmount: [
    { required: true, message: '请输入分款金额', trigger: 'blur' },
    { validator: validateDetailAmountNotExceedNode, trigger: ['blur', 'change'] }
  ]
};

const syncTaskVariables = () => {
  if (form.value.accountManagerIds) {
    taskVariables.value.accountManagerId = form.value.accountManagerIds;
  } else if (form.value.managerUserIds?.length) {
    taskVariables.value.accountManagerId = form.value.managerUserIds.map((id) => String(id)).join(',');
  } else {
    taskVariables.value.accountManagerId = '';
  }
};

const loadDetailList = async () => {
  if (!form.value.accountInstallmentId) return;
  detailLoading.value = true;
  try {
    const res = await getErpFinAccountInstallmentDetailList({
      accountInstallmentId: form.value.accountInstallmentId
    });
    detailList.value = res.data || [];
  } finally {
    detailLoading.value = false;
  }
};

const refreshInstallment = async () => {
  if (!form.value.accountInstallmentId) return;
  const res = await getFinAccountInstallment(form.value.accountInstallmentId);
  Object.assign(form.value, res.data);
  syncTaskVariables();
};

const loadData = async (id: string | number) => {
  proxy?.$modal.loading('正在加载数据，请稍后...');
  try {
    const res = await getFinAccountInstallment(id);
    Object.assign(form.value, res.data);
    syncTaskVariables();
    await loadDetailList();
  } finally {
    proxy?.$modal.closeLoading();
  }
};

const handleAddDetail = () => {
  if (!form.value.accountInstallmentId) {
    proxy?.$modal.msgWarning('回款数据未加载');
    return;
  }
  if (!canEditDetail.value) {
    return;
  }
  if (!canAddDetail.value) {
    proxy?.$modal.msgWarning('剩余可分金额为0，无法新增分款');
    return;
  }
  showProjectDialog.value = true;
};

const handleProjectSelected = (data: any) => {
  selectedProject.value = data.project;
  if (data.project.contractFlag !== '1') {
    showContractDialog.value = true;
  } else {
    fillDetailForm(data.project, data.contract);
    getPaymentStages(data.contract.contractId);
  }
};

const handleContractSelected = (contract: any) => {
  if (selectedProject.value) {
    fillDetailForm(selectedProject.value, contract);
    getPaymentStages(contract.contractId);
  }
};

const fillDetailForm = (project: any, contract: any) => {
  const totalPriceRaw = contract?.totalPrice;
  detailFormContractTotalPrice.value =
    totalPriceRaw !== undefined && totalPriceRaw !== null && totalPriceRaw !== '' ? Number(totalPriceRaw) : undefined;
  Object.assign(detailForm, {
    installmentDetailId: undefined,
    accountInstallmentId: form.value.accountInstallmentId,
    projectId: project.projectId || project.id,
    projectCode: project.projectCode,
    projectName: project.projectName,
    contractId: contract?.contractId || contract?.id,
    contractCode: contract?.contractCode || '',
    contractName: contract?.contractName || '',
    paymentStageId: undefined,
    detailAmount: undefined,
    remark: undefined,
    contractTotalPrice: undefined,
    contractPaymentPercentage: undefined,
    contractPaymentAmount: undefined
  });
  detailDialog.title = '新增分款明细';
  detailDialog.visible = true;
};

const syncAddDetailAmountFromSelectedStage = () => {
  if (!detailDialog.visible || detailForm.installmentDetailId) return;
  let next: number | undefined;
  if (detailForm.paymentStageId != null && detailForm.paymentStageId !== '') {
    const raw = selectedStageContractShareAmount.value;
    const n = raw != null && !Number.isNaN(Number(raw)) ? Number(raw) : NaN;
    if (!Number.isNaN(n) && n > 0) {
      const rounded = Math.round(n * 100) / 100;
      next = rounded < 0.01 ? 0.01 : rounded;
    }
  }
  detailForm.detailAmount = next;
  if (detailFormRef.value) {
    nextTick(() => detailFormRef.value?.validateField('detailAmount'));
  }
};

const handleEditDetail = async (row: FinAccountInstallmentDetailVO) => {
  Object.assign(detailForm, row);
  detailDialog.title = '编辑分款明细';
  detailDialog.visible = true;
  const tp = row.contractTotalPrice;
  detailFormContractTotalPrice.value =
    tp !== undefined && tp !== null && !Number.isNaN(Number(tp)) ? Number(tp) : undefined;
  await getPaymentStages(detailForm.contractId);
  nextTick(() => detailFormRef.value?.validateField('detailAmount'));
};

const handleDeleteDetail = async (row: FinAccountInstallmentDetailVO) => {
  await proxy?.$modal.confirm('是否确认删除该分款明细？');
  await deleteInstallmentDetailByBo({
    installmentDetailId: row.installmentDetailId,
    accountInstallmentId: form.value.accountInstallmentId!
  });
  proxy?.$modal.msgSuccess('删除成功');
  await loadDetailList();
  await refreshInstallment();
};

const submitDetailForm = async () => {
  const valid = await detailFormRef.value?.validate();
  if (!valid) return;
  detailButtonLoading.value = true;
  try {
    if (detailForm.installmentDetailId) {
      await updateFinAccountInstallmentDetail(detailForm);
      proxy?.$modal.msgSuccess('修改成功');
    } else {
      await addFinAccountInstallmentDetail(detailForm);
      proxy?.$modal.msgSuccess('新增成功');
    }
    detailDialog.visible = false;
    await loadDetailList();
    await refreshInstallment();
  } finally {
    detailButtonLoading.value = false;
  }
};

const cancelDetail = () => {
  detailDialog.visible = false;
};

watch(
  () => detailDialog.visible,
  (val) => {
    if (!val) {
      Object.assign(detailForm, initDetailForm);
      detailFormContractTotalPrice.value = undefined;
    }
  }
);

watch(
  () => [
    detailDialog.visible,
    detailForm.installmentDetailId,
    detailForm.paymentStageId,
    paymentStageList.value,
    detailFormContractTotalPrice.value
  ],
  () => {
    syncAddDetailAmountFromSelectedStage();
  },
  { flush: 'post' }
);

onMounted(() => {
  routeParams.value = route.query;
  const id = routeParams.value.id as string | number;
  if (id) {
    loadData(id);
  }
});

const submitForm = () => {
  proxy?.$modal.msgWarning('分款审核由财务派发后自动发起，无需在此提交');
};

const handleApprovalRecord = () => {
  approvalRecordRef.value?.init(form.value.accountInstallmentId);
};

const approvalVerifyOpen = async () => {
  if (!validateAllocationBeforeSubmit()) {
    return;
  }
  syncTaskVariables();
  await submitVerifyRef.value?.openDialog(routeParams.value.taskId);
};

const submitCallback = () => {
  proxy?.$tab.closePage(route);
  router.go(-1);
};
</script>
