import type { BillArchiveStatus, LeaseLedgerRow } from '../types';

export interface LedgerImportRow {
  year: number;
  month: number;
  plateNo: string;
  patch: Partial<LeaseLedgerRow>;
  otherIncomeAmounts: number[];
  otherDeductionAmounts: number[];
}

type ImportColumnType = 'string' | 'amount' | 'integer' | 'boolean';

interface ImportScalarColumn {
  header: string;
  key: keyof LeaseLedgerRow;
  type?: ImportColumnType;
  required?: boolean;
}

const INCOME_AMOUNT_HEADERS = ['其他收入金额', '其他收入金额2', '其他收入金额3'] as const;
const DEDUCTION_AMOUNT_HEADERS = ['其他减免金额', '其他减免金额2', '其他减免金额3'] as const;

/** 可导入字段（不含系统自动计算项） */
export const LEDGER_MANUAL_IMPORT_COLUMNS: ImportScalarColumn[] = [
  { header: '年份', key: 'year', type: 'integer', required: true },
  { header: '月份', key: 'month', type: 'integer', required: true },
  { header: '车牌号码', key: 'plateNo', required: true },
  { header: '业务部门', key: 'dept' },
  { header: '业务员', key: 'salesman' },
  { header: '客户名称', key: 'customerName' },
  { header: '项目名称', key: 'projectName' },
  { header: '享免政策', key: 'exemptionPolicy' },
  { header: '提车日期', key: 'pickupDate' },
  { header: '退车日期', key: 'returnDate' },
  { header: '保证金', key: 'deposit' },
  { header: '合同标的租金', key: 'contractRent', type: 'amount' },
  { header: '付款周期月数', key: 'paymentCycleMonths', type: 'integer' },
  { header: '保险采购金额', key: 'insurancePurchaseAmount', type: 'amount' },
  { header: '保险有效天数', key: 'insuranceEffectiveDays', type: 'integer' },
  { header: '保险上浮费', key: 'insuranceSurcharge', type: 'amount' },
  { header: '氢费承担方式', key: 'hydrogenBorneBy' },
  { header: '维保包干', key: 'maintenancePackageEnabled', type: 'boolean' },
  { header: '维保包干单价', key: 'maintenanceUnitPricePerKm', type: 'amount' },
  { header: '里程数', key: 'mileage', type: 'amount' },
  { header: '里程减免单价', key: 'mileageDeductionRate', type: 'amount' },
  { header: '实收金额', key: 'receivedAmount', type: 'amount' },
  { header: '居间费', key: 'brokerageFee', type: 'amount' },
  { header: '其他', key: 'otherCost', type: 'amount' },
  { header: '其他减免金额明细内容', key: 'otherDeductionDetail' },
  { header: '备注', key: 'remark' },
  { header: '账单状态', key: 'archiveStatus' },
  { header: '资产归属', key: 'assetOwnership' },
];

const TEMPLATE_SAMPLE: Record<string, string> = {
  年份: '2026',
  月份: '1',
  车牌号码: '沪A61121F',
  业务部门: '业务二部',
  业务员: '刘念念',
  客户名称: '安徽驰远供应链管理有限公司',
  项目名称: '安徽驰远供应链管租赁项目',
  享免政策: '帕力安18T里程优惠政策',
  提车日期: '2024-11-30',
  退车日期: '',
  保证金: '/',
  合同标的租金: '4500',
  付款周期月数: '1',
  保险采购金额: '12000',
  保险有效天数: '365',
  保险上浮费: '0',
  氢费承担方式: '我司承担',
  维保包干: '否',
  维保包干单价: '0',
  里程数: '0',
  里程减免单价: '0.5',
  实收金额: '4500',
  其他收入金额: '120.00',
  其他收入金额2: '',
  其他收入金额3: '',
  其他减免金额: '30.00',
  其他减免金额2: '',
  其他减免金额3: '',
  居间费: '500',
  其他: '0',
  其他减免金额明细内容: '',
  备注: '',
  账单状态: '草稿',
  资产归属: '租赁',
};

function parseCsvLine(line: string): string[] {
  const result: string[] = [];
  let current = '';
  let inQuotes = false;

  for (let i = 0; i < line.length; i += 1) {
    const ch = line[i];
    if (ch === '"') {
      inQuotes = !inQuotes;
      continue;
    }
    if (ch === ',' && !inQuotes) {
      result.push(current.trim());
      current = '';
      continue;
    }
    current += ch;
  }

  result.push(current.trim());
  return result;
}

function normalizeHeader(value: string): string {
  return value.replace(/^\*/, '').trim();
}

function parseAmount(value: string): number {
  const cleaned = value.replace(/,/g, '').trim();
  if (!cleaned) return 0;
  const num = Number(cleaned);
  return Number.isFinite(num) ? Math.round(num * 100) / 100 : 0;
}

function parseInteger(value: string): number {
  const cleaned = value.trim();
  if (!cleaned) return 0;
  const num = Number(cleaned);
  return Number.isFinite(num) ? Math.trunc(num) : 0;
}

function parseBoolean(value: string): boolean | undefined {
  const text = value.trim();
  if (!text) return undefined;
  if (['是', 'true', '1', '启用', 'Y', 'y'].includes(text)) return true;
  if (['否', 'false', '0', '关闭', 'N', 'n'].includes(text)) return false;
  return undefined;
}

function parseArchiveStatus(value: string): BillArchiveStatus | undefined {
  const text = value.trim();
  if (text === '草稿' || text === '未归档' || text === '已归档') return text;
  return undefined;
}

function parseHydrogenBorneBy(value: string): LeaseLedgerRow['hydrogenBorneBy'] | undefined {
  const text = value.trim();
  if (text === '我司承担' || text === '客户承担') return text;
  return undefined;
}

function parseAssetOwnership(value: string): LeaseLedgerRow['assetOwnership'] | undefined {
  const text = value.trim();
  if (text === '自有' || text === '租赁' || text === '挂靠') return text;
  return undefined;
}

function collectAmountColumns(headers: string[], names: readonly string[]): number[] {
  const cols: number[] = [];
  headers.forEach((cell, index) => {
    if (names.includes(cell as typeof names[number])) cols.push(index);
  });
  return cols;
}

function parseScalarValue(
  column: ImportScalarColumn,
  raw: string,
): string | number | boolean | BillArchiveStatus | LeaseLedgerRow['hydrogenBorneBy'] | LeaseLedgerRow['assetOwnership'] | undefined {
  const text = raw.trim();
  if (!text) return undefined;

  switch (column.type) {
    case 'amount':
      return parseAmount(text);
    case 'integer':
      return parseInteger(text);
    case 'boolean': {
      const bool = parseBoolean(text);
      return bool;
    }
    default:
      break;
  }

  if (column.key === 'archiveStatus') return parseArchiveStatus(text);
  if (column.key === 'hydrogenBorneBy') return parseHydrogenBorneBy(text);
  if (column.key === 'assetOwnership') return parseAssetOwnership(text);
  if (column.key === 'deposit') return text;
  return text;
}

function buildTemplateHeaders(): string[] {
  return [
    ...LEDGER_MANUAL_IMPORT_COLUMNS.map((col) => (col.required ? `*${col.header}` : col.header)),
    ...INCOME_AMOUNT_HEADERS,
    ...DEDUCTION_AMOUNT_HEADERS,
  ];
}

function buildTemplateSampleRow(): string[] {
  const headers = buildTemplateHeaders().map(normalizeHeader);
  return headers.map((header) => TEMPLATE_SAMPLE[header] ?? '');
}

export function lineItemsShowDetailColumns(items: { reason: string; remark: string }[]): boolean {
  return items.some((item) => item.reason.trim() || item.remark.trim());
}

export function downloadLedgerBatchImportTemplate(): void {
  const headers = buildTemplateHeaders();
  const sample = buildTemplateSampleRow();
  const csv = `\uFEFF${headers.join(',')}\n${sample.join(',')}`;
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const anchor = document.createElement('a');
  anchor.href = url;
  anchor.download = '租赁业务台账导入模板.csv';
  anchor.click();
  URL.revokeObjectURL(url);
}

export function parseLedgerBatchImportFile(text: string): LedgerImportRow[] {
  const lines = text
    .replace(/^\uFEFF/, '')
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);

  let headerIndex = -1;
  let headerCells: string[] = [];
  const columnIndex = new Map<string, number>();

  for (let i = 0; i < lines.length; i += 1) {
    const cells = parseCsvLine(lines[i]).map(normalizeHeader);
    if (cells.includes('年份') && cells.includes('月份') && (cells.includes('车牌号码') || cells.includes('车牌号'))) {
      headerIndex = i;
      headerCells = cells;
      cells.forEach((cell, index) => columnIndex.set(cell, index));
      if (!columnIndex.has('车牌号码') && columnIndex.has('车牌号')) {
        columnIndex.set('车牌号码', columnIndex.get('车牌号')!);
      }
      break;
    }
  }

  if (headerIndex < 0) return [];

  const incomeAmountCols = collectAmountColumns(headerCells, INCOME_AMOUNT_HEADERS);
  const deductionAmountCols = collectAmountColumns(headerCells, DEDUCTION_AMOUNT_HEADERS);

  const rows: LedgerImportRow[] = [];
  for (let i = headerIndex + 1; i < lines.length; i += 1) {
    const cells = parseCsvLine(lines[i]);
    const year = parseInteger(cells[columnIndex.get('年份') ?? -1] ?? '');
    const month = parseInteger(cells[columnIndex.get('月份') ?? -1] ?? '');
    const plateNo = (cells[columnIndex.get('车牌号码') ?? -1] ?? '').trim();
    if (!year || !month || !plateNo) continue;

    const patch: Partial<LeaseLedgerRow> = {};
    for (const column of LEDGER_MANUAL_IMPORT_COLUMNS) {
      if (column.key === 'year' || column.key === 'month' || column.key === 'plateNo') continue;
      const colIdx = columnIndex.get(column.header);
      if (colIdx == null) continue;
      const parsed = parseScalarValue(column, cells[colIdx] ?? '');
      if (parsed === undefined) continue;
      (patch as Record<string, unknown>)[column.key] = parsed;
    }

    const otherIncomeAmounts = incomeAmountCols
      .map((col) => parseAmount(cells[col] ?? ''))
      .filter((amount) => amount > 0);
    const otherDeductionAmounts = deductionAmountCols
      .map((col) => parseAmount(cells[col] ?? ''))
      .filter((amount) => amount > 0);

    const hasPatch = Object.keys(patch).length > 0;
    if (!hasPatch && otherIncomeAmounts.length === 0 && otherDeductionAmounts.length === 0) continue;

    rows.push({ year, month, plateNo, patch, otherIncomeAmounts, otherDeductionAmounts });
  }

  return rows;
}

export function buildAmountOnlyLineItems(amounts: number[]): LeaseLedgerRow['otherIncomeItems'] {
  return amounts.map((amount) => ({ reason: '', amount, remark: '' }));
}

export function applyLedgerImportToRow(
  row: LeaseLedgerRow,
  importRow: LedgerImportRow,
): LeaseLedgerRow {
  return {
    ...row,
    ...importRow.patch,
    ...(importRow.otherIncomeAmounts.length > 0
      ? { otherIncomeItems: buildAmountOnlyLineItems(importRow.otherIncomeAmounts) }
      : {}),
    ...(importRow.otherDeductionAmounts.length > 0
      ? { otherDeductionItems: buildAmountOnlyLineItems(importRow.otherDeductionAmounts) }
      : {}),
  };
}

export function createDraftLedgerRowFromImport(
  importRow: LedgerImportRow,
  idSuffix: number,
): LeaseLedgerRow {
  const plateKey = importRow.plateNo.replace(/\s+/g, '');
  const base: LeaseLedgerRow = {
    id: `import-${importRow.year}-${importRow.month}-${plateKey}-${idSuffix}`,
    status: '未收款',
    archiveStatus: '草稿',
    maintainerName: '批量导入',
    year: importRow.year,
    month: importRow.month,
    plateNo: importRow.plateNo,
    dept: '',
    salesman: '',
    vehicleBrand: '',
    vehicleModel: '',
    customerName: '',
    projectName: '',
    valueAddedService: '',
    exemptionPolicy: '',
    pickupDate: '',
    contractStartDate: '',
    contractEndDate: '',
    periodStartDate: '',
    returnDate: '',
    avgDays: 0,
    deposit: '/',
    contractRent: 0,
    paymentCycleMonths: 1,
    serviceFee: 0,
    maintenancePackageEnabled: false,
    maintenanceUnitPricePerKm: 0,
    mileage: 0,
    customerBearsMaintenance: false,
    linkedMaintenanceIds: [],
    linkedAccidentIds: [],
    linkedReceiptIds: [],
    hydrogenBorneBy: '',
    isLatestBill: false,
    receivableTotal: 0,
    receivableRent: 0,
    monthlyIncome: 0,
    monthlyRent: 0,
    maintenanceIncome: 0,
    insuranceSurcharge: 0,
    opsFeeIncome: 0,
    otherIncome: 0,
    mileageDeduction: 0,
    otherDeduction: 0,
    receivedAmount: 0,
    invoiceDate: '',
    actualPaymentDate: '',
    paymentMethod: '',
    vehicleStandardCost: 0,
    vehicleActualCost: 0,
    insuranceFee: 0,
    hydrogenFee: 0,
    opsFeeCost: 0,
    brokerageFee: 0,
    otherCost: 0,
    totalCost: 0,
    profitLoss: 0,
    gpsMileage: '',
    otherDeductionDetail: '',
    assetOwnership: '自有',
    signingCompany: '',
    remark: '',
  };

  return applyLedgerImportToRow(base, importRow);
}

export function matchLedgerImportRow(row: LeaseLedgerRow, importRow: LedgerImportRow): boolean {
  return row.year === importRow.year
    && row.month === importRow.month
    && row.plateNo.replace(/\s+/g, '') === importRow.plateNo.replace(/\s+/g, '');
}
