import * as XLSX from 'xlsx';
import type { LeaseBusinessDetailRow } from '../types';
import { DETAIL_EXPORT_HEADERS, DETAIL_EXPORT_SPECS } from '../components/tableColumns';
import { applyDetailCalculations } from './calc-detail';
import { getContractRef, getVehicleRef, isPlateInVehicleSystem } from './system-ref';

/** 导入模板列（不含公式列；业务部门/业务员由系统合同反写） */
export const DETAIL_IMPORT_TEMPLATE_HEADERS = [
  '年份',
  '月份',
  '付款日期',
  '车牌号码',
  '客户名称',
  '增值服务',
  '享免政策',
  '提车日期',
  '合同生效日期',
  '合同到期日期',
  '起始日期',
  '退车日期',
  '平均天数',
  '押金',
  '合同标的租金',
  '维保包干收入',
  '保险上浮费',
  '运维费',
  '其他收入',
  '里程减免金额',
  '其他减免金额',
  '实收金额',
  '开票日期',
  '实际付款日期',
  '付款方式',
  '车辆标准成本',
  '车辆实际成本',
  '保险费',
  '运维费',
  '居间费',
  '其他',
  'GPS里程',
  '减免金额明细内容',
  '资产归属',
  '签约公司',
  '备注',
] as const;

export const DETAIL_IMPORT_REQUIRED_HEADERS = [
  '年份',
  '月份',
  '付款日期',
  '车牌号码',
  '客户名称',
  '提车日期',
  '合同生效日期',
  '合同到期日期',
  '平均天数',
  '押金',
  '合同标的租金',
  '实收金额',
  '资产归属',
  '签约公司',
] as const;

export interface DetailImportErrorRow {
  reason: string;
  rawCells: (string | number)[];
}

export interface DetailImportParseResult {
  success: LeaseBusinessDetailRow[];
  errors: DetailImportErrorRow[];
  /** 上传文件表头（用于错误日志） */
  fileHeaders: string[];
}

const TEMPLATE_SAMPLE: Record<string, string | number> = {
  年份: 2026,
  月份: 2,
  付款日期: '2026-02-05',
  车牌号码: '沪A52898F',
  客户名称: '上海虹钦物流有限公司',
  增值服务: '',
  享免政策: '',
  提车日期: '2025-12-08',
  合同生效日期: '2025-12-01',
  合同到期日期: '2026-11-30',
  起始日期: '2026-02-01',
  退车日期: '',
  平均天数: 1,
  押金: 20000,
  合同标的租金: 4500,
  维保包干收入: 0,
  保险上浮费: 0,
  运维费: 0,
  其他收入: 0,
  里程减免金额: 0,
  其他减免金额: 0,
  实收金额: 4500,
  开票日期: '2026-02-06',
  实际付款日期: '2026-02-05',
  付款方式: '月度预付',
  车辆标准成本: 3900,
  车辆实际成本: 0,
  保险费: 0,
  居间费: 500,
  其他: 0,
  GPS里程: '',
  减免金额明细内容: '',
  资产归属: '浙江羚牛氢能科技有限公司',
  签约公司: '浙江羚牛氢能科技有限公司',
  备注: '',
};

const HEADER_TO_KEY: Record<string, keyof LeaseBusinessDetailRow> = {
  年份: 'year',
  月份: 'month',
  业务部门: 'businessDept',
  业务员: 'salesperson',
  付款日期: 'paymentDate',
  车牌号码: 'plateNo',
  车型: 'vehicleType',
  客户名称: 'customerName',
  增值服务: 'valueAddedService',
  享免政策: 'exemptionPolicy',
  提车日期: 'pickupDate',
  合同生效日期: 'contractStartDate',
  合同到期日期: 'contractEndDate',
  起始日期: 'periodStartDate',
  退车日期: 'returnDate',
  平均天数: 'avgDays',
  押金: 'deposit',
  合同标的租金: 'contractRent',
  应收租金: 'receivableRent',
  月度租金: 'monthlyRent',
  维保包干收入: 'maintenanceIncome',
  保险上浮费: 'insuranceSurcharge',
  其他收入: 'otherIncome',
  里程减免金额: 'mileageDeduction',
  其他减免金额: 'otherDeduction',
  实收金额: 'receivedAmount',
  开票日期: 'invoiceDate',
  实际付款日期: 'actualPaymentDate',
  付款方式: 'paymentMethod',
  车辆标准成本: 'vehicleStandardCost',
  车辆实际成本: 'vehicleActualCost',
  保险费: 'insuranceFee',
  氢费: 'hydrogenFee',
  居间费: 'brokerageFee',
  其他: 'otherCost',
  GPS里程: 'gpsMileage',
  'GPS 里程': 'gpsMileage',
  减免金额明细内容: 'otherDeductionDetail',
  其他减免金额明细内容: 'otherDeductionDetail',
  资产归属: 'assetOwner',
  签约公司: 'signingCompany',
  备注: 'remark',
};

const IMPORT_NUMERIC_KEYS = new Set<keyof LeaseBusinessDetailRow>([
  'year', 'month', 'avgDays',
  'contractRent', 'receivableRent', 'monthlyRent',
  'maintenanceIncome', 'insuranceSurcharge', 'opsFeeIncome', 'otherIncome',
  'mileageDeduction', 'otherDeduction', 'receivedAmount',
  'vehicleStandardCost', 'vehicleActualCost', 'insuranceFee', 'hydrogenFee',
  'opsFeeCost', 'brokerageFee', 'otherCost',
]);

const IMPORT_TEXT_KEYS = new Set<keyof LeaseBusinessDetailRow>([
  'businessDept', 'salesperson', 'paymentDate', 'plateNo', 'vehicleType', 'customerName',
  'valueAddedService', 'exemptionPolicy', 'pickupDate', 'contractStartDate', 'contractEndDate',
  'periodStartDate', 'returnDate', 'invoiceDate', 'actualPaymentDate', 'paymentMethod',
  'gpsMileage', 'otherDeductionDetail', 'assetOwner', 'signingCompany', 'remark',
]);

const REQUIRED_NUMERIC_HEADERS = new Set(['年份', '月份', '平均天数', '合同标的租金', '实收金额']);

function isCellEmpty(value: unknown): boolean {
  if (value === null || value === undefined) return true;
  return String(value).trim() === '';
}

function parseNumber(value: unknown): number {
  if (value === null || value === undefined || value === '') return 0;
  const n = Number(String(value).replace(/,/g, ''));
  return Number.isFinite(n) ? n : 0;
}

function parseDeposit(value: unknown): number | string {
  if (value === null || value === undefined || value === '') return 0;
  const raw = String(value).trim();
  if (raw === '/') return '/';
  return parseNumber(raw);
}

function normalizeHeader(header: string): string {
  return header.replace(/（必填）/g, '').trim();
}

function resolveHeaderKey(header: string): keyof LeaseBusinessDetailRow | undefined {
  return HEADER_TO_KEY[normalizeHeader(header)];
}

function validateRequiredFields(
  headers: string[],
  cells: (string | number)[],
): string[] {
  const reasons: string[] = [];
  const headerIndex = new Map(headers.map((h, i) => [normalizeHeader(h), i]));

  DETAIL_IMPORT_REQUIRED_HEADERS.forEach((required) => {
    const idx = headerIndex.get(required);
    const raw = idx === undefined ? undefined : cells[idx];
    if (required === '押金') {
      if (isCellEmpty(raw)) reasons.push(`${required}不能为空`);
      return;
    }
    if (REQUIRED_NUMERIC_HEADERS.has(required)) {
      if (isCellEmpty(raw)) reasons.push(`${required}不能为空`);
      return;
    }
    if (isCellEmpty(raw)) reasons.push(`${required}不能为空`);
  });

  return reasons;
}

function enrichDraftFromSystem(draft: Partial<LeaseBusinessDetailRow>): void {
  if (!draft.plateNo) return;
  const vehicle = getVehicleRef(draft.plateNo);
  if (vehicle) {
    draft.vehicleType = vehicle.brandModel || draft.vehicleType || '';
  }
  if (draft.customerName) {
    const contract = getContractRef(draft.plateNo, draft.customerName);
    if (contract) {
      draft.businessDept = contract.businessDept;
      draft.salesperson = contract.salesperson;
    }
  }
}

function parseRowDraft(
  headers: string[],
  cells: (string | number)[],
  index: number,
): Partial<LeaseBusinessDetailRow> {
  const draft: Partial<LeaseBusinessDetailRow> = {
    id: `import-${Date.now()}-${index}`,
  };
  let opsFeeColIndex = 0;

  headers.forEach((header, colIndex) => {
    const normalized = normalizeHeader(header);
    let key = resolveHeaderKey(header);
    if (normalized === '运维费') {
      opsFeeColIndex += 1;
      key = opsFeeColIndex === 1 ? 'opsFeeIncome' : 'opsFeeCost';
    }
    if (!key) return;
    const raw = cells[colIndex];
    if (key === 'deposit') {
      (draft as Record<string, unknown>)[key] = parseDeposit(raw);
    } else if (IMPORT_NUMERIC_KEYS.has(key)) {
      const num = parseNumber(raw);
      if (key === 'mileageDeduction' || key === 'otherDeduction') {
        (draft as Record<string, unknown>)[key] = num > 0 ? -Math.abs(num) : num;
      } else {
        (draft as Record<string, unknown>)[key] = num;
      }
    } else if (IMPORT_TEXT_KEYS.has(key)) {
      (draft as Record<string, unknown>)[key] = String(raw ?? '').trim();
    }
  });

  enrichDraftFromSystem(draft);
  return draft;
}

function rowToExportCells(row: LeaseBusinessDetailRow): string[] {
  let opsIncomeWritten = false;
  return DETAIL_EXPORT_SPECS.map((spec) => {
    const header = spec.title;
    if (header === '运维费') {
      if (!opsIncomeWritten) {
        opsIncomeWritten = true;
        return row.opsFeeIncome === 0 ? '' : String(row.opsFeeIncome);
      }
      return row.opsFeeCost === 0 ? '' : String(row.opsFeeCost);
    }
    const key = spec.key;
    const raw = row[key];
    if (key === 'deposit') {
      if (raw === '/' || raw === '') return raw === '/' ? '/' : '';
      return typeof raw === 'number' && raw === 0 ? '' : String(raw);
    }
    if (typeof raw === 'number') return raw === 0 ? '' : String(raw);
    return raw == null ? '' : String(raw);
  });
}

export function downloadDetailImportTemplate(): void {
  const sampleRow = DETAIL_IMPORT_TEMPLATE_HEADERS.map((header) => TEMPLATE_SAMPLE[header] ?? '');
  const opsIndexes = DETAIL_IMPORT_TEMPLATE_HEADERS.reduce<number[]>((acc, h, i) => {
    if (h === '运维费') acc.push(i);
    return acc;
  }, []);
  if (opsIndexes[1] !== undefined) sampleRow[opsIndexes[1]] = 0;

  const sheet = XLSX.utils.aoa_to_sheet([Array.from(DETAIL_IMPORT_TEMPLATE_HEADERS), sampleRow]);
  const book = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(book, sheet, '租赁业务明细');
  XLSX.writeFile(book, '租赁业务明细导入模板.xlsx');
}

export function downloadDetailImportErrorLog(
  errors: DetailImportErrorRow[],
  fileHeaders: string[],
): void {
  if (!errors.length) return;
  const headers = ['导入失败原因', ...(fileHeaders.length ? fileHeaders : Array.from(DETAIL_IMPORT_TEMPLATE_HEADERS))];
  const body = errors.map((err) => [err.reason, ...err.rawCells]);
  const sheet = XLSX.utils.aoa_to_sheet([headers, ...body]);
  const book = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(book, sheet, '导入失败记录');
  XLSX.writeFile(book, `租赁业务明细导入失败记录_${Date.now()}.xlsx`);
}

export function exportDetailRows(rows: LeaseBusinessDetailRow[]): void {
  const body = [DETAIL_EXPORT_HEADERS, ...rows.map(rowToExportCells)];
  const sheet = XLSX.utils.aoa_to_sheet(body);
  const book = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(book, sheet, '租赁业务明细');
  XLSX.writeFile(book, `租赁业务明细_${Date.now()}.xlsx`);
}

export async function parseDetailImportFile(file: File): Promise<DetailImportParseResult> {
  const buffer = await file.arrayBuffer();
  const book = XLSX.read(buffer, { type: 'array' });
  const sheet = book.Sheets[book.SheetNames[0]];
  const matrix = XLSX.utils.sheet_to_json<(string | number)[]>(sheet, { header: 1, defval: '' }) as (string | number)[][];
  if (matrix.length < 2) {
    return { success: [], errors: [], fileHeaders: [] };
  }

  const fileHeaders = matrix[0].map((cell) => String(cell).trim());
  const success: LeaseBusinessDetailRow[] = [];
  const errors: DetailImportErrorRow[] = [];

  matrix.slice(1).forEach((cells, index) => {
    if (!cells.some((cell) => String(cell).trim())) return;

    const rawCells = fileHeaders.map((_, colIndex) => cells[colIndex] ?? '');
    const requiredReasons = validateRequiredFields(fileHeaders, cells);
    if (requiredReasons.length > 0) {
      errors.push({ reason: requiredReasons.join('；'), rawCells });
      return;
    }

    const draft = parseRowDraft(fileHeaders, cells, index);
    const plateNo = String(draft.plateNo ?? '').trim();
    if (!isPlateInVehicleSystem(plateNo)) {
      errors.push({ reason: '车牌号不存在', rawCells });
      return;
    }

    success.push(applyDetailCalculations(draft));
  });

  return { success, errors, fileHeaders };
}
