import {
  Table,
  TableHeader,
  TableColumn,
  TableBody,
  TableRow,
  TableCell,
  Tooltip,
} from "@heroui/react";
import { saveAs } from "file-saver";

type LogQsoItem = {
  id: number;
  qso_index?: number | null;
  time_on?: string | null;
  dx_call?: string | null;
  my_rst?: string | null;
  my_serial?: string | null;
  dx_rst?: string | null;
  dx_serial?: string | null;
  rx_wwl?: string | null;
  rx_exchange?: string | null;
  mode_code?: string | null;
  new_exchange?: boolean | null;
  new_wwl?: boolean | null;
  new_dxcc?: boolean | null;
  duplicate_qso?: boolean | null;
  points?: number | null;
  remarks?: string | null;
};

type QsoResultItem = {
  log_qso_id: number;
  penalty_points?: number | null;
  error_code?: string | null;
  error_side?: string | null;
  match_confidence?: string | null;
  match_type?: string | null;
  error_flags?: string[] | null;
};

type QsoOverrideInfo = {
  reason?: string | null;
  forced_status?: string | null;
  forced_matched_log_qso_id?: number | null;
  forced_points?: number | null;
  forced_penalty?: number | null;
};

type LogQsoTableProps = {
  qsos: LogQsoItem[];
  locale: string;
  formatDateTime: (value: string | null | undefined, locale: string) => string;
  officialQsoResults: Record<number, QsoResultItem>;
  qsoOverrides: Record<number, QsoOverrideInfo>;
  emptyLabel: string;
  callsign?: string | null;
};

export default function LogQsoTable({
  qsos,
  locale,
  formatDateTime,
  officialQsoResults,
  qsoOverrides,
  emptyLabel,
  callsign,
}: LogQsoTableProps) {
  if (!qsos || qsos.length === 0) {
    return <div>{emptyLabel}</div>;
  }

  const getOverrideLabel = (override?: QsoOverrideInfo) => {
    if (!override) return "—";
    if (override.forced_status && override.forced_status !== "AUTO") {
      return `STATUS: ${override.forced_status}`;
    }
    if (override.forced_matched_log_qso_id) {
      return `MATCH: ${override.forced_matched_log_qso_id}`;
    }
    if (
      override.forced_points !== null && override.forced_points !== undefined ||
      override.forced_penalty !== null && override.forced_penalty !== undefined
    ) {
      return "BODY: override";
    }
    return "OVERRIDE";
  };

  const toCsvValue = (value: string | number | null | undefined) => {
    if (value === null || value === undefined || value === "—") return "";
    return String(value).replace(/"/g, '""');
  };

  const handleCsvExport = () => {
    const header = [
      "#",
      "Time",
      "Callsign",
      "Mode",
      "My RST",
      "My Serial",
      "DX RST",
      "DX Serial",
      "WWL",
      "Exchange",
      "Points",
      "Penalty",
      "New WWL",
      "New DXCC",
      "Dupe",
      "Error",
      "Side",
      "Match",
      "Override",
      "Note",
    ];

    const lines = qsos.map((qso) => {
      const override =
        qsoOverrides[qso.id] ??
        qsoOverrides[String(qso.id) as unknown as number];
      const matchResult = officialQsoResults[qso.id];
      const note = override
        ? override.reason ?? "—"
        : qso.remarks || "—";

      const row = [
        qso.qso_index ?? "",
        formatDateTime(qso.time_on ?? null, locale),
        qso.dx_call || "—",
        qso.mode_code || "—",
        qso.my_rst || "—",
        qso.my_serial || "—",
        qso.dx_rst || "—",
        qso.dx_serial || "—",
        qso.rx_wwl || "—",
        qso.rx_exchange || "—",
        qso.points ?? "—",
        typeof matchResult?.penalty_points === "number"
          ? matchResult?.penalty_points
          : "—",
        qso.new_wwl ? "N" : "—",
        qso.new_dxcc ? "N" : "—",
        qso.duplicate_qso ? "D" : "—",
        matchResult?.error_code ?? "—",
        matchResult?.error_side && matchResult?.error_side !== "NONE"
          ? matchResult?.error_side
          : "—",
        matchResult?.match_confidence ?? "—",
        getOverrideLabel(override),
        note,
      ];

      return row.map((value) => `"${toCsvValue(value)}"`).join(",");
    });

    const csv = [header.join(","), ...lines].join("\n");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
    const safeCallsign = callsign?.trim() || "qso_table";
    const fileName = safeCallsign.replace(/\\s+/g, "_");
    saveAs(blob, `${fileName}.csv`);
  };

  return (
    <div className="space-y-2">
      <div className="flex justify-end">
        <a
          href="#"
          className="text-xs text-foreground-500 hover:underline"
          onClick={(event) => {
            event.preventDefault();
            handleCsvExport();
          }}
        >
          CSV
        </a>
      </div>
      <div className="overflow-x-auto">
      <Table
        aria-label="QSO table"
        isCompact
        radius="sm"
        removeWrapper
        className="min-w-max"
        classNames={{
          th: "py-1 px-1 text-[11px] leading-tight",
          td: "py-0.5 px-1 text-[11px] leading-tight",
        }}
      >
        <TableHeader>
          <TableColumn>#</TableColumn>
          <TableColumn>Čas</TableColumn>
          <TableColumn>Volací znak</TableColumn>
          <TableColumn>Mode</TableColumn>
          <TableColumn>RST odeslané</TableColumn>
          <TableColumn>Číslo odeslané</TableColumn>
          <TableColumn>RST přijaté</TableColumn>
          <TableColumn>Číslo přijaté</TableColumn>
          <TableColumn>WWL</TableColumn>
          <TableColumn>Exchange</TableColumn>
          <TableColumn>Body</TableColumn>
          <TableColumn>Penalizace</TableColumn>
          <TableColumn>Nové WWL</TableColumn>
          <TableColumn>Nové DXCC</TableColumn>
          <TableColumn>Dupl.</TableColumn>
          <TableColumn>Chyba</TableColumn>
          <TableColumn>Strana</TableColumn>
          <TableColumn>Match</TableColumn>
          <TableColumn>Zásah</TableColumn>
          <TableColumn>Poznámka</TableColumn>
        </TableHeader>
        <TableBody items={qsos} className="text-[11px] leading-tight">
          {(qso) => {
            const override =
              qsoOverrides[qso.id] ??
              qsoOverrides[String(qso.id) as unknown as number];
            const matchResult = officialQsoResults[qso.id];
            const matchConfidence = matchResult?.match_confidence ?? "—";
            const matchTooltipLines: string[] = [];
            if (matchResult?.match_type) {
              matchTooltipLines.push(`Type: ${matchResult.match_type}`);
            }
            if (Array.isArray(matchResult?.error_flags) && matchResult.error_flags.length > 0) {
              matchTooltipLines.push(`Flags: ${matchResult.error_flags.join(", ")}`);
            }
            const cellStyle = override ? { backgroundColor: "#FEF3C7" } : undefined;
            const note = override
              ? override.reason ?? "—"
              : qso.remarks || "—";
            const overrideLabel = getOverrideLabel(override);
            return (
              <TableRow key={qso.id}>
                <TableCell style={cellStyle}>{qso.qso_index ?? "—"}</TableCell>
                <TableCell style={cellStyle}>
                  {formatDateTime(qso.time_on ?? null, locale)}
                </TableCell>
                <TableCell style={cellStyle}>{qso.dx_call || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.mode_code || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.my_rst || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.my_serial || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.dx_rst || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.dx_serial || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.rx_wwl || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.rx_exchange || "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.points ?? "—"}</TableCell>
                <TableCell style={cellStyle}>
                  {typeof officialQsoResults[qso.id]?.penalty_points === "number"
                    ? officialQsoResults[qso.id]?.penalty_points
                    : "—"}
                </TableCell>
                <TableCell style={cellStyle}>{qso.new_wwl ? "N" : "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.new_dxcc ? "N" : "—"}</TableCell>
                <TableCell style={cellStyle}>{qso.duplicate_qso ? "D" : "—"}</TableCell>
                <TableCell style={cellStyle}>
                  {officialQsoResults[qso.id]?.error_code ?? "—"}
                </TableCell>
                <TableCell style={cellStyle}>
                  {officialQsoResults[qso.id]?.error_side &&
                  officialQsoResults[qso.id]?.error_side !== "NONE"
                    ? officialQsoResults[qso.id]?.error_side
                    : "—"}
                </TableCell>
                <TableCell style={cellStyle}>
                  {matchConfidence === "PARTIAL" && matchTooltipLines.length > 0 ? (
                    <Tooltip
                      content={
                        <div className="text-xs leading-snug">
                          {matchTooltipLines.map((line, index) => (
                            <div key={index}>{line}</div>
                          ))}
                        </div>
                      }
                    >
                      <span className="cursor-help">{matchConfidence}</span>
                    </Tooltip>
                  ) : (
                    matchConfidence
                  )}
                </TableCell>
                <TableCell style={cellStyle}>{overrideLabel}</TableCell>
                <TableCell style={cellStyle}>{note}</TableCell>
              </TableRow>
            );
          }}
        </TableBody>
      </Table>
      </div>
    </div>
  );
}
