const HEADER_ALIASES: Record<string, string[]> = {
  primary_country_code: [
    "primarycountry",
    "primarycountry**",
    "primarycountrycode",
    "country",
    "primarycountry[**]",
  ],
  approved_document_name: [
    "approveddocumentname",
    "documentname",
    "approveddocname",
    "approveddocument",
  ],
  sent_email_name: ["sentemailname", "sentemail", "sentemailid", "sentemailkey"],
  last_open: ["lastopen", "openlast", "lastopendate"],
  opened: ["opened", "isopened", "openflag"],
  total_opens: ["totalopens", "opens", "opencount"],
  clicked: ["clicked", "isclicked", "clickflag"],
  last_click: ["lastclick", "clicklast", "lastclickdate"],
  total_clicks: ["totalclicks", "clicks", "clickcount"],
  sent_date: ["sentdate", "date", "emailsentdate"],
  brand: ["brand", "emailbrand", "documentbrand", "productbrand", "product"],
};

export const REQUIRED_FIELDS = [
  "primary_country_code",
  "approved_document_name",
  "sent_email_name",
] as const;

export type CanonicalHeader = keyof typeof HEADER_ALIASES;

const HEADER_LOOKUP = Object.entries(HEADER_ALIASES).reduce<Record<string, CanonicalHeader>>(
  (acc, [canonical, aliases]) => {
    for (const alias of aliases) {
      acc[alias] = canonical as CanonicalHeader;
    }
    return acc;
  },
  {},
);

export function normalizeHeaderToken(value: unknown) {
  return String(value ?? "")
    .trim()
    .toLowerCase()
    .replace(/\s+/g, "")
    .replace(/[^a-z0-9*\[\]]/g, "");
}

export function canonicalHeader(value: unknown): CanonicalHeader | null {
  const token = normalizeHeaderToken(value);
  if (!token) return null;

  if (HEADER_LOOKUP[token]) return HEADER_LOOKUP[token];

  // Handles labels like "Primary Country [**]"
  const fallback = token.replace(/\*/g, "");
  if (HEADER_LOOKUP[fallback]) return HEADER_LOOKUP[fallback];

  return null;
}

export type HeaderMap = Partial<Record<CanonicalHeader, number>>;

export function buildHeaderMap(row: unknown[]): HeaderMap {
  const mapping: HeaderMap = {};

  row.forEach((cell, index) => {
    const canonical = canonicalHeader(cell);
    if (canonical && mapping[canonical] === undefined) {
      mapping[canonical] = index;
    }
  });

  return mapping;
}

export function scoreHeaderMap(headerMap: HeaderMap) {
  const recognized = Object.keys(headerMap).length;
  const requiredFound = REQUIRED_FIELDS.filter(
    (field) => headerMap[field] !== undefined,
  ).length;

  return { recognized, requiredFound };
}

export function findHeaderRow(rows: unknown[][], maxScan = 40) {
  let best: { rowIndex: number; map: HeaderMap; recognized: number; requiredFound: number } | null =
    null;

  const scanLimit = Math.min(rows.length, maxScan);

  for (let i = 0; i < scanLimit; i += 1) {
    const map = buildHeaderMap(rows[i] ?? []);
    const { recognized, requiredFound } = scoreHeaderMap(map);

    if (recognized === 0) continue;

    if (!best || requiredFound > best.requiredFound || recognized > best.recognized) {
      best = { rowIndex: i, map, recognized, requiredFound };
    }

    if (requiredFound === REQUIRED_FIELDS.length && recognized >= 5) {
      return { rowIndex: i, map };
    }
  }

  if (best && best.requiredFound === REQUIRED_FIELDS.length) {
    return { rowIndex: best.rowIndex, map: best.map };
  }

  return null;
}
