/**
 * Authority Catalog — Known institutions with online status checking portals.
 *
 * Each authority defines: endpoint, payload builder, HTML response parser,
 * and status derivation logic. Start with hardcoded entries, design for
 * future DB storage linked to Address Book contacts.
 */

import type { ExternalStatusRow, ExternalDocStatus } from "../types";

// ── Authority config interface ──

export interface AuthorityConfig {
  /** Unique ID (e.g., "primaria-cluj") */
  id: string;
  /** Display name */
  name: string;
  /** POST endpoint URL */
  endpoint: string;
  /** Content-Type for POST */
  contentType: string;
  /** Whether petitioner name is required */
  requiresPetitionerName: boolean;
  /** Build the POST body from entry data */
  buildPayload: (params: {
    regNumber: string;
    petitionerName: string;
    regDate: string; // dd.mm.yyyy
  }) => string;
  /** Parse HTML response into status rows */
  parseResponse: (html: string) => ExternalStatusRow[];
  /** Derive semantic status from the last row */
  deriveStatus: (row: ExternalStatusRow) => ExternalDocStatus;
  /** Match a contact name to this authority */
  matchesContact: (contactName: string) => boolean;
}

// ── HTML parsing helpers ──

/** Strip HTML tags and normalize whitespace */
function stripTags(html: string): string {
  return html
    .replace(/<[^>]*>/g, "")
    .replace(/&nbsp;/gi, " ")
    .replace(/\s+/g, " ")
    .trim();
}

/** Extract <td> contents from a <tr> string */
function extractCells(trHtml: string): string[] {
  const cells: string[] = [];
  const tdRegex = /<td[^>]*>([\s\S]*?)<\/td>/gi;
  let match = tdRegex.exec(trHtml);
  while (match) {
    cells.push(stripTags(match[1] ?? ""));
    match = tdRegex.exec(trHtml);
  }
  return cells;
}

// ── Primaria Cluj-Napoca ──

function parseClujResponse(html: string): ExternalStatusRow[] {
  // Find the table after "Starea documentului" caption/heading
  const anchorIdx = html.indexOf("Starea documentului");
  if (anchorIdx === -1) return [];

  // Find the first <table> after the anchor
  const tableStart = html.indexOf("<table", anchorIdx);
  if (tableStart === -1) return [];
  const tableEnd = html.indexOf("</table>", tableStart);
  if (tableEnd === -1) return [];

  const tableHtml = html.substring(tableStart, tableEnd + 8);

  // Extract all <tr> rows
  const rows: ExternalStatusRow[] = [];
  const trRegex = /<tr[^>]*>([\s\S]*?)<\/tr>/gi;
  let isFirst = true;
  let match = trRegex.exec(tableHtml);

  while (match) {
    // Skip header row
    if (isFirst) {
      isFirst = false;
      match = trRegex.exec(tableHtml);
      continue;
    }

    const cells = extractCells(match[1] ?? "");
    if (cells.length >= 8) {
      rows.push({
        dataVenire: cells[0] ?? "",
        oraVenire: cells[1] ?? "",
        sursa: cells[2] ?? "",
        dataTrimitere: cells[3] ?? "",
        oraTrimitere: cells[4] ?? "",
        destinatie: cells[5] ?? "",
        modRezolvare: cells[6] ?? "",
        comentarii: cells[7] ?? "",
      });
    }

    match = trRegex.exec(tableHtml);
  }

  return rows;
}

function deriveClujStatus(row: ExternalStatusRow): ExternalDocStatus {
  const text = `${row.modRezolvare} ${row.comentarii}`.toLowerCase();

  if (/solu[tț]ionat|rezolvat|aprobat/.test(text)) return "solutionat";
  if (/respins/.test(text)) return "respins";
  if (/trimis/.test(text)) return "trimis";
  if (/[iî]n\s*operare/.test(text)) return "in-operare";

  // If destinatie is set but no resolution, it's been forwarded
  if (row.destinatie && !row.modRezolvare) return "trimis";

  return "necunoscut";
}

const PRIMARIA_CLUJ: AuthorityConfig = {
  id: "primaria-cluj",
  name: "Primaria Municipiului Cluj-Napoca",
  endpoint: "https://e-primariaclujnapoca.ro/registratura/nrinreg.php",
  contentType: "application/x-www-form-urlencoded",
  requiresPetitionerName: true,

  buildPayload({ regNumber, petitionerName, regDate }) {
    const params = new URLSearchParams();
    params.set("Nr", regNumber);
    params.set("Nume", petitionerName);
    params.set("Data", regDate);
    params.set("btn_cauta", "Caută cerere");
    return params.toString();
  },

  parseResponse: parseClujResponse,
  deriveStatus: deriveClujStatus,

  matchesContact(contactName: string): boolean {
    const lower = contactName.toLowerCase();
    return (
      (lower.includes("primaria") || lower.includes("primăria")) &&
      lower.includes("cluj")
    );
  },
};

// ── Catalog ──

export const AUTHORITY_CATALOG: AuthorityConfig[] = [PRIMARIA_CLUJ];

/** Get authority config by ID */
export function getAuthority(id: string): AuthorityConfig | undefined {
  return AUTHORITY_CATALOG.find((a) => a.id === id);
}

/** Find matching authority for a contact name */
export function findAuthorityForContact(
  contactName: string,
): AuthorityConfig | undefined {
  return AUTHORITY_CATALOG.find((a) => a.matchesContact(contactName));
}
