import ExcelJS from 'exceljs';

import { formatPriceLikeBackend, parsePriceValue } from './priceCompare';

const MAX_ROWS = 5000;

export type ParsedWarehousePriceRow = {
  drug_name: string;
  drug_number: string;
  market_price: number;
  price: number;
};

export type ParseWarehousePriceResult = {
  items: ParsedWarehousePriceRow[];
  invalidCount: number;
  rowCount: number;
};

function normalizeCell(value: ExcelJS.CellValue): string {
  if (value === null || value === undefined) {
    return '';
  }
  if (typeof value === 'object' && 'text' in value) {
    return String(value.text ?? '').trim();
  }
  if (typeof value === 'number') {
    return Number.isInteger(value) ? String(value) : String(value).trim();
  }
  return String(value).trim();
}

function normalizeHeader(value: string): string {
  return value.replace(/\s+/g, '').replace(/\u3000/g, '');
}

const NUMBER_ALIASES = ['商品编码', '药品编码', '编码', 'drug_number'];
const NAME_ALIASES = ['通用名', '药品名称', '药名', 'drug_name'];
const MARKET_ALIASES = ['每克供货价', '供货价', 'market_price'];
const PRICE_ALIASES = ['每克零售价', '建议售价', '零售价', 'price'];

function buildHeaderIndexMap(headerRow: ExcelJS.Row): Record<string, number> {
  const map: Record<string, number> = {};
  headerRow.eachCell({ includeEmpty: true }, (cell, colNumber) => {
    const key = normalizeHeader(normalizeCell(cell.value));
    if (key) {
      map[key] = colNumber;
    }
  });
  return map;
}

function pickColumn(
  headerMap: Record<string, number>,
  aliases: string[],
): number | undefined {
  for (const alias of aliases) {
    const col = headerMap[normalizeHeader(alias)];
    if (col) {
      return col;
    }
  }
  return undefined;
}

function getCellNumber(row: ExcelJS.Row, col?: number): number {
  if (!col) {
    return 0;
  }
  return parsePriceValue(row.getCell(col).value);
}

function getCellText(row: ExcelJS.Row, col?: number): string {
  if (!col) {
    return '';
  }
  return normalizeCell(row.getCell(col).value);
}

function rowIsEmpty(row: ExcelJS.Row): boolean {
  let hasValue = false;
  row.eachCell({ includeEmpty: false }, (cell) => {
    if (normalizeCell(cell.value) !== '') {
      hasValue = true;
    }
  });
  return !hasValue;
}

export async function parseWarehousePriceExcelBuffer(
  buffer: ArrayBuffer,
): Promise<ParseWarehousePriceResult> {
  const workbook = new ExcelJS.Workbook();
  await workbook.xlsx.load(buffer);

  const sheet = workbook.worksheets[0];
  if (!sheet) {
    return { items: [], invalidCount: 0, rowCount: 0 };
  }

  const headerRow = sheet.getRow(1);
  const headerMap = buildHeaderIndexMap(headerRow);

  const numberCol = pickColumn(headerMap, NUMBER_ALIASES);
  const nameCol = pickColumn(headerMap, NAME_ALIASES);
  const marketCol = pickColumn(headerMap, MARKET_ALIASES);
  const priceCol = pickColumn(headerMap, PRICE_ALIASES);

  const items: ParsedWarehousePriceRow[] = [];
  let invalidCount = 0;
  const rowCount = Math.min(sheet.rowCount, MAX_ROWS + 1);

  for (let rowIndex = 2; rowIndex <= rowCount; rowIndex++) {
    const row = sheet.getRow(rowIndex);
    if (rowIsEmpty(row)) {
      continue;
    }

    const drugNumber = getCellText(row, numberCol);
    const drugName = getCellText(row, nameCol);
    const marketPrice = getCellNumber(row, marketCol);
    const price = getCellNumber(row, priceCol);

    if (!drugName && !drugNumber && marketPrice === 0 && price === 0) {
      continue;
    }

    if (!drugName && !drugNumber) {
      invalidCount++;
      continue;
    }

    items.push({
      drug_name: drugName,
      drug_number: drugNumber,
      market_price: formatPriceLikeBackend(marketPrice),
      price: formatPriceLikeBackend(price),
    });
  }

  return {
    items,
    invalidCount,
    rowCount: Math.max(0, rowCount - 1),
  };
}
