import type { LeaseBusinessDetailRow } from '../types';
import { sumHydrogenFeeForDetailRow } from './hydrogen-fee';
import { resolveSettlementMonths } from './system-ref';

/** 对齐 Excel「租赁车辆收入明细表」公式列 */
export const DETAIL_CALCULATED_KEYS = [
  'receivableTotal',
  'monthlyIncome',
  'outstanding',
  'vehicleActualCost',
  'totalCost',
  'profitLoss',
] as const;

export type DetailCalculatedKey = (typeof DETAIL_CALCULATED_KEYS)[number];

function roundMoney(value: number): number {
  return Math.round(value * 100) / 100;
}

type IncomeAdjustments = Pick<
  LeaseBusinessDetailRow,
  | 'maintenanceIncome'
  | 'insuranceSurcharge'
  | 'opsFeeIncome'
  | 'otherIncome'
  | 'mileageDeduction'
  | 'otherDeduction'
>;

/** 账单月自然日天数 */
export function daysInMonth(year: number, month: number): number {
  if (!year || !month) return 30;
  return new Date(year, month, 0).getDate();
}

/** 本月在租天数（原型：有起始/退车日期则按区间，否则整月） */
export function calcLeaseDaysInMonth(
  year: number,
  month: number,
  periodStartDate: string,
  returnDate: string,
): number {
  if (!year || !month) return 0;
  const monthStart = new Date(year, month - 1, 1);
  const monthEnd = new Date(year, month, 0);
  let start = periodStartDate ? new Date(periodStartDate.slice(0, 10)) : monthStart;
  let end = returnDate ? new Date(returnDate.slice(0, 10)) : monthEnd;
  if (start < monthStart) start = monthStart;
  if (end > monthEnd) end = monthEnd;
  if (end < start) return 0;
  const ms = end.getTime() - start.getTime();
  return Math.max(0, Math.floor(ms / 86400000) + 1);
}

/** 平均天数 = 本月在租天数 / 当月天数 */
export function calcDetailAvgDays(
  year: number,
  month: number,
  periodStartDate: string,
  returnDate: string,
): number {
  const leaseDays = calcLeaseDaysInMonth(year, month, periodStartDate, returnDate);
  const dim = daysInMonth(year, month);
  if (!dim) return 0;
  return roundMoney(leaseDays / dim);
}

/** 月度租金 = 合同标的租金（月标准），付款周期大于 1 时仍按月标准展示 */
export function calcDetailMonthlyRent(contractRent: number): number {
  return roundMoney(contractRent);
}

/** 应收租金 = 合同标的租金 × 结算周期月数 */
export function calcDetailReceivableRent(contractRent: number, settlementMonths: number): number {
  return roundMoney(contractRent * settlementMonths);
}

/** 应收合计 = 应收租金 + 收入调整项 */
export function calcDetailReceivableTotal(
  receivableRent: number,
  adjustments: IncomeAdjustments,
): number {
  return roundMoney(
    receivableRent
    + adjustments.maintenanceIncome
    + adjustments.insuranceSurcharge
    + adjustments.opsFeeIncome
    + adjustments.otherIncome
    + adjustments.mileageDeduction
    + adjustments.otherDeduction,
  );
}

/** 月度收入 = 月度租金 + 收入侧调整项（同应收合计调整段） */
export function calcDetailMonthlyIncome(
  monthlyRent: number,
  adjustments: IncomeAdjustments,
): number {
  return roundMoney(
    monthlyRent
    + adjustments.maintenanceIncome
    + adjustments.insuranceSurcharge
    + adjustments.opsFeeIncome
    + adjustments.otherIncome
    + adjustments.mileageDeduction
    + adjustments.otherDeduction,
  );
}

/** 车辆实际成本 = 车辆标准成本 × 平均天数 */
export function calcDetailVehicleActualCost(vehicleStandardCost: number, avgDays: number): number {
  return roundMoney(vehicleStandardCost * avgDays);
}

/** 总成本 = 车辆实际成本 + 保险费 + 氢费 + 运维费(成本) + 居间费 + 其他 */
export function calcDetailTotalCost(
  row: Pick<
    LeaseBusinessDetailRow,
    'vehicleActualCost' | 'insuranceFee' | 'hydrogenFee' | 'opsFeeCost' | 'brokerageFee' | 'otherCost'
  >,
): number {
  return roundMoney(
    row.vehicleActualCost
    + row.insuranceFee
    + row.hydrogenFee
    + row.opsFeeCost
    + row.brokerageFee
    + row.otherCost,
  );
}

/** 未收 = 应收合计 − 实收金额 */
export function calcDetailOutstanding(receivableTotal: number, receivedAmount: number): number {
  return roundMoney(receivableTotal - receivedAmount);
}

/** 盈亏 = 月度收入 − 总成本 */
export function calcDetailProfitLoss(monthlyIncome: number, totalCost: number): number {
  return roundMoney(monthlyIncome - totalCost);
}

const EMPTY_TEXT_FIELDS = {
  businessDept: '',
  salesperson: '',
  paymentDate: '',
  plateNo: '',
  vehicleType: '',
  customerName: '',
  valueAddedService: '',
  exemptionPolicy: '',
  pickupDate: '',
  contractStartDate: '',
  contractEndDate: '',
  periodStartDate: '',
  returnDate: '',
  invoiceDate: '',
  actualPaymentDate: '',
  paymentMethod: '',
  gpsMileage: '',
  otherDeductionDetail: '',
  assetOwner: '',
  signingCompany: '',
  remark: '',
} as const;

/** 补齐缺省字段并套用 Excel 公式列 */
export function applyDetailCalculations(
  row: Partial<LeaseBusinessDetailRow> & { id: string },
): LeaseBusinessDetailRow {
  const adjustments: IncomeAdjustments = {
    maintenanceIncome: row.maintenanceIncome ?? 0,
    insuranceSurcharge: row.insuranceSurcharge ?? 0,
    opsFeeIncome: row.opsFeeIncome ?? 0,
    otherIncome: row.otherIncome ?? 0,
    mileageDeduction: row.mileageDeduction ?? 0,
    otherDeduction: row.otherDeduction ?? 0,
  };

  const year = row.year ?? 0;
  const month = row.month ?? 0;
  const contractRent = row.contractRent ?? 0;
  const settlementMonths = resolveSettlementMonths({
    ...row,
    year,
    month,
    contractRent,
  } as LeaseBusinessDetailRow);

  const computedAvgDays = calcDetailAvgDays(
    year,
    month,
    row.periodStartDate ?? '',
    row.returnDate ?? '',
  );
  const avgDays = row.avgDays && row.avgDays > 0 ? row.avgDays : computedAvgDays;
  const monthlyRent = calcDetailMonthlyRent(contractRent);
  const receivableRent = row.receivableRent && row.receivableRent > 0
    ? row.receivableRent
    : calcDetailReceivableRent(contractRent, settlementMonths);
  const receivedAmount = row.receivedAmount ?? 0;
  const vehicleStandardCost = row.vehicleStandardCost ?? 0;

  const vehicleActualCost = calcDetailVehicleActualCost(vehicleStandardCost, avgDays);
  const monthlyIncome = calcDetailMonthlyIncome(monthlyRent, adjustments);
  const receivableTotal = calcDetailReceivableTotal(receivableRent, adjustments);
  const hydrogenFee = sumHydrogenFeeForDetailRow({
    plateNo: row.plateNo ?? '',
    customerName: row.customerName ?? '',
    year,
    month,
    pickupDate: row.pickupDate ?? '',
    returnDate: row.returnDate ?? '',
  });
  const totalCost = calcDetailTotalCost({
    vehicleActualCost,
    insuranceFee: row.insuranceFee ?? 0,
    hydrogenFee,
    opsFeeCost: row.opsFeeCost ?? 0,
    brokerageFee: row.brokerageFee ?? 0,
    otherCost: row.otherCost ?? 0,
  });
  const outstanding = calcDetailOutstanding(receivableTotal, receivedAmount);
  const profitLoss = calcDetailProfitLoss(monthlyIncome, totalCost);

  return {
    id: row.id,
    year: row.year ?? 0,
    month: row.month ?? 0,
    ...EMPTY_TEXT_FIELDS,
    ...row,
    deposit: row.deposit ?? 0,
    contractRent,
    receivableRent,
    monthlyRent,
    ...adjustments,
    receivedAmount,
    vehicleStandardCost,
    avgDays,
    insuranceFee: row.insuranceFee ?? 0,
    hydrogenFee,
    opsFeeCost: row.opsFeeCost ?? 0,
    brokerageFee: row.brokerageFee ?? 0,
    otherCost: row.otherCost ?? 0,
    vehicleActualCost,
    monthlyIncome,
    receivableTotal,
    totalCost,
    outstanding,
    profitLoss,
    archiveStatus: row.archiveStatus ?? 'active',
    reconciledAt: row.reconciledAt ?? '',
  };
}
