import React, { useMemo } from "react";
import {
  Button,
  Card,
  CardBody,
  CardHeader,
  Divider,
  Table,
  TableBody,
  TableCell,
  TableColumn,
  TableHeader,
  TableRow,
} from "@heroui/react";
import type { LogResult, LogOverride } from "@/components/RoundEvaluationLogOverrides.types";

type GroupedResults = Array<{ key: string; items: LogResult[] }>;

type Props = {
  items: LogResult[];
  overrides: Record<number, LogOverride>;
  onEdit: (logId: number) => void;
};

function PencilIcon({ className }: { className?: string }) {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 20 20"
      fill="currentColor"
      className={className ?? "h-4 w-4"}
    >
      <path d="M13.586 3.586a2 2 0 0 1 2.828 2.828l-8.25 8.25a2 2 0 0 1-.878.518l-3.122.89a.75.75 0 0 1-.926-.926l.89-3.122a2 2 0 0 1 .518-.878l8.25-8.25Z" />
      <path d="M12.475 4.697 4.75 12.422l-.69 2.422 2.422-.69 7.725-7.725-1.732-1.732Z" />
    </svg>
  );
}

function groupBy(items: LogResult[], getKey: (r: LogResult) => string): GroupedResults {
  const map = new Map<string, LogResult[]>();
  items.forEach((item) => {
    const key = getKey(item);
    if (!map.has(key)) map.set(key, []);
    map.get(key)!.push(item);
  });
  return Array.from(map.entries()).map(([key, list]) => ({ key, items: list }));
}

function sortGroups(groups: GroupedResults): GroupedResults {
  return [...groups].sort((a, b) => {
    const aItem = a.items[0];
    const bItem = b.items[0];
    const bandOrder =
      (aItem?.band?.order ?? Number.MAX_SAFE_INTEGER) -
      (bItem?.band?.order ?? Number.MAX_SAFE_INTEGER);
    if (bandOrder !== 0) return bandOrder;
    const categoryOrder =
      (aItem?.category?.order ?? Number.MAX_SAFE_INTEGER) -
      (bItem?.category?.order ?? Number.MAX_SAFE_INTEGER);
    if (categoryOrder !== 0) return categoryOrder;
    const powerOrder =
      (aItem?.power_category?.order ?? Number.MAX_SAFE_INTEGER) -
      (bItem?.power_category?.order ?? Number.MAX_SAFE_INTEGER);
    if (powerOrder !== 0) return powerOrder;
    const bandName = aItem?.band?.name ?? "";
    const bandNameB = bItem?.band?.name ?? "";
    if (bandName !== bandNameB) return bandName.localeCompare(bandNameB);
    const categoryName = aItem?.category?.name ?? "";
    const categoryNameB = bItem?.category?.name ?? "";
    if (categoryName !== categoryNameB) return categoryName.localeCompare(categoryNameB);
    const powerName = aItem?.power_category?.name ?? "";
    const powerNameB = bItem?.power_category?.name ?? "";
    return powerName.localeCompare(powerNameB);
  });
}

function resolveNames(item: LogResult): [string | null, string | null, string | null] {
  const band = item.band?.name ?? null;
  const category = item.category?.name ?? null;
  const power = item.power_category?.name ?? null;
  return [band, category, power];
}

type RankField = "rank_overall" | "rank_in_category";

function isCheckCategory(item: LogResult) {
  const name = item.category?.name?.toLowerCase() ?? "";
  return name.includes("check");
}

function isPowerA(item: LogResult) {
  const name = item.power_category?.name?.toLowerCase() ?? "";
  return name === "a";
}

function sortResults(items: LogResult[], rankField: RankField) {
  return [...items].sort((a, b) => {
    const ra = a[rankField] ?? Number.MAX_SAFE_INTEGER;
    const rb = b[rankField] ?? Number.MAX_SAFE_INTEGER;
    if (ra !== rb) return ra - rb;
    const sa = a.official_score ?? 0;
    const sb = b.official_score ?? 0;
    if (sa !== sb) return sb - sa;
    const qa = a.valid_qso_count ?? 0;
    const qb = b.valid_qso_count ?? 0;
    return qb - qa;
  });
}

function formatNumber(value: number | null | undefined) {
  if (value === null || value === undefined) return "—";
  if (Number.isInteger(value)) return value.toString();
  return value.toFixed(1);
}

function formatRatio(score?: number | null, qso?: number | null) {
  if (!score || !qso || qso === 0) return "—";
  return (score / qso).toFixed(2);
}

function renderGroup(
  group: GroupedResults,
  title: string,
  rankField: RankField,
  includePowerInHeading: boolean,
  overrides: Record<number, LogOverride>,
  onEdit: (logId: number) => void
) {
  if (group.length === 0) return [];
  return group.map(({ key, items }) => {
    const sample = items[0];
    const [bandName, categoryName, powerName] = resolveNames(sample);
    const headingParts = [bandName, categoryName, title];
    if (includePowerInHeading && !isCheckCategory(sample)) {
      headingParts.push(powerName);
    }
    const heading = headingParts.filter(Boolean).join(" ");
    const sorted = sortResults(items, rankField);

    return (
      <Card key={key} className="mb-3">
        <CardHeader className="py-2">
          <div className="flex items-center justify-between w-full gap-2">
            <span className="text-md font-semibold">{heading}</span>
          </div>
        </CardHeader>
        <Divider />
        <CardBody className="py-2">
          <Table
            radius="sm"
            isCompact
            aria-label={heading}
            removeWrapper
            fullWidth
            classNames={{
              th: "py-1 px-1 text-[11px] leading-tight",
              td: "py-0.5 px-1 text-[11px] leading-tight bg-transparent",
            }}
          >
            <TableHeader>
              <TableColumn className="whitespace-nowrap">Pořadí</TableColumn>
              <TableColumn className="whitespace-nowrap">Značka</TableColumn>
              <TableColumn className="whitespace-nowrap">Lokátor</TableColumn>
              <TableColumn className="whitespace-nowrap">Kategorie</TableColumn>
              <TableColumn className="whitespace-nowrap">Pásmo</TableColumn>
              <TableColumn className="whitespace-nowrap">Výkon [W]</TableColumn>
              <TableColumn className="whitespace-nowrap">Výkonová kategorie</TableColumn>
              <TableColumn className="whitespace-nowrap">Body celkem</TableColumn>
              <TableColumn className="whitespace-nowrap">Počet QSO</TableColumn>
              <TableColumn className="whitespace-nowrap">Body/QSO</TableColumn>
              <TableColumn className="whitespace-nowrap">ODX</TableColumn>
              <TableColumn className="whitespace-nowrap">Anténa</TableColumn>
              <TableColumn className="whitespace-nowrap">Ant. height</TableColumn>
              <TableColumn className="whitespace-nowrap">Status</TableColumn>
              <TableColumn className="whitespace-nowrap">Komentář rozhodčího</TableColumn>
              <TableColumn className="whitespace-nowrap">Akce</TableColumn>
            </TableHeader>
            <TableBody emptyContent="No rows to display" items={sorted}  className="text-[11px] leading-tight">
              {(item) => {
                const override = overrides[item.log_id];
                const rowHighlight =
                  !!override &&
                  (override.forced_log_status && override.forced_log_status !== "AUTO" ||
                    override.forced_band_id ||
                    override.forced_category_id ||
                    override.forced_power_category_id ||
                    override.forced_power_w !== null && override.forced_power_w !== undefined ||
                    override.forced_sixhr_category !== null && override.forced_sixhr_category !== undefined);
                return (
                  <TableRow key={item.id} className={rowHighlight ? "bg-warning-100 hover:bg-warning-300" : "hover:bg-default-200"}>
                    <TableCell className="whitespace-nowrap">{item[rankField] ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.log?.pcall ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">
                      {item.log?.pwwlo ?? item.log?.locator ?? "—"}
                    </TableCell>
                    <TableCell className="whitespace-nowrap">{item.category?.name ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.band?.name ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">
                      {formatNumber(item.log?.power_watt)}
                    </TableCell>
                    <TableCell className="whitespace-nowrap">
                      {item.powerCategory?.name ?? item.power_category?.name ?? "—"}
                    </TableCell>
                    <TableCell className="whitespace-nowrap">{formatNumber(item.official_score)}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.valid_qso_count ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">
                      {formatRatio(item.official_score, item.valid_qso_count)}
                    </TableCell>
                    <TableCell className="whitespace-nowrap">{item.log?.codxc ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.log?.sante ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.log?.santh ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{item.status ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">{override?.reason ?? "—"}</TableCell>
                    <TableCell className="whitespace-nowrap">
                      <Button
                        isIconOnly
                        size="sm"
                        variant="light"
                        className="min-w-0 w-4 h-4 p-0"
                        onPress={() => onEdit(item.log_id)}
                        aria-label="Upravit override"
                      >
                        <PencilIcon className="h-4 w-4" />
                      </Button>
                    </TableCell>
                  </TableRow>
                );
              }}
            </TableBody>
          </Table>
        </CardBody>
      </Card>
    );
  });
}

function renderOverallWithPowers(
  overalls: GroupedResults,
  powers: GroupedResults,
  title: string,
  overrides: Record<number, LogOverride>,
  onEdit: (logId: number) => void
) {
  if (overalls.length === 0) return null;

  const powerIndex = powers.reduce<Record<string, GroupedResults>>((acc, group) => {
    const [bandId, categoryId] = group.key.split("|");
    const key = `${bandId}|${categoryId}`;
    acc[key] = acc[key] || [];
    acc[key].push(group);
    return acc;
  }, {});

  return sortGroups(overalls).flatMap(({ key, items }) => {
    const [bandId, categoryId] = key.split("|");
    const powerGroups = sortGroups(powerIndex[`${bandId}|${categoryId}`] ?? []);

    return [
      ...renderGroup([{ key, items }], title, "rank_overall", false, overrides, onEdit),
      ...renderGroup(powerGroups, "", "rank_in_category", true, overrides, onEdit),
    ];
  });
}

export default React.memo(function RoundEvaluationLogOverridesTable({
  items,
  overrides,
  onEdit,
}: Props) {
  const grouped = useMemo(() => {
    const isSixhr = (r: LogResult) => (r.log?.sixhr_category ?? false) === true;
    const sixh = items.filter((r) => isSixhr(r));
    const standard = items.filter((r) => !isSixhr(r));
    const powerEligible = standard.filter(
      (r) => !isCheckCategory(r) && !isPowerA(r) && r.power_category && r.rank_in_category !== null
    );

    const groupOverall = (list: LogResult[]) =>
      groupBy(list, (r) => `${r.band?.id ?? "null"}|${r.category?.id ?? "null"}`);
    const groupPower = (list: LogResult[]) =>
      groupBy(
        list,
        (r) =>
          `${r.band?.id ?? "null"}|${r.category?.id ?? "null"}|${r.power_category?.id ?? "null"}`
      );

    return {
      sixhOverall: groupOverall(sixh),
      standardOverall: groupOverall(standard),
      standardPower: groupPower(powerEligible),
    };
  }, [items]);

  return (
    <>
      {renderOverallWithPowers(grouped.standardOverall, grouped.standardPower, "", overrides, onEdit)}
      {renderOverallWithPowers(grouped.sixhOverall, [], "6H", overrides, onEdit)}
    </>
  );
});
