import { Alert, Stack } from "@mantine/core";
import {
  IconAlertTriangle,
  IconCoin,
  IconListDetails,
  IconStars,
  IconTags,
  IconUsersGroup,
} from "@tabler/icons-react";
import { useMemo } from "react";
import { usePromoTheme } from "@/routes/promo-code-campaigns/_components/appearance";
import {
  StatTiles,
  type StatTileSpec,
} from "@/routes/promo-code-campaigns/_components/StatTiles";
import { eventTypeLabel, type EventSummary } from "@/lib/features/event-analytics/types";

const fmtInt = (n: number) => n.toLocaleString("en-US");

const fmtMoney = (n: number, currency: string) =>
  `${currency} ${n.toLocaleString("en-US", {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })}`;

/**
 * KPI row, using the shared promo tiles so the figures animate on a filter
 * change and take their colours from the same accent as the charts below.
 */
export default function SummaryCards({
  summary,
  loading,
}: {
  summary: EventSummary | null;
  loading: boolean;
}) {
  const { series } = usePromoTheme();

  const tiles = useMemo<StatTileSpec[]>(() => {
    const [c0, c1, c2, c3, c4] = series(5);
    const s = summary;

    /*
     * Revenue is deliberately not one number.
     *
     * A tile shows a single figure, and these currencies are not comparable, so
     * the tile reports the largest currency total and names it, with the rest in
     * the hint. Adding them would produce a number that means nothing.
     */
    const topCurrency = s?.revenueByCurrency[0] ?? null;
    const otherCurrencies = (s?.revenueByCurrency ?? []).slice(1);

    return [
      {
        key: "events",
        label: "Total events",
        value: s?.totalEvents ?? 0,
        color: c0.from,
        colorTo: c0.to,
        icon: <IconListDetails size={18} stroke={1.8} />,
        hint:
          s?.firstEventAt && s?.lastEventAt
            ? `${s.firstEventAt.slice(0, 10)} → ${s.lastEventAt.slice(0, 10)}`
            : "No events in range",
      },
      {
        key: "members",
        label: "Members",
        value: s?.uniqueMembers ?? 0,
        color: c1.from,
        colorTo: c1.to,
        icon: <IconUsersGroup size={18} stroke={1.8} />,
        hint: `${fmtInt(s?.uniqueEventTypes ?? 0)} event type${s?.uniqueEventTypes === 1 ? "" : "s"
          } in range`,
      },
      {
        key: "top-event",
        label: "Top event",
        value: s?.topEventType?.events ?? 0,
        color: c2.from,
        colorTo: c2.to,
        icon: <IconTags size={18} stroke={1.8} />,
        percent:
          s?.topEventType && s.totalEvents
            ? (s.topEventType.events / s.totalEvents) * 100
            : 0,
        hint: s?.topEventType
          ? eventTypeLabel(s.topEventType.eventType)
          : "Nothing recorded",
      },
      {
        key: "points",
        label: "Points earned",
        value: s?.totalPoints ?? 0,
        color: c3.from,
        colorTo: c3.to,
        icon: <IconStars size={18} stroke={1.8} />,
        percent:
          s?.totalEvents ? (s.pointsEvents / s.totalEvents) * 100 : 0,
        hint: `${fmtInt(s?.pointsEvents ?? 0)} of ${fmtInt(
          s?.totalEvents ?? 0,
        )} events carried points`,
      },
      {
        key: "revenue",
        label: topCurrency ? `Revenue (${topCurrency.currency})` : "Revenue",
        value: topCurrency?.revenue ?? 0,
        color: c4.from,
        colorTo: c4.to,
        icon: <IconCoin size={18} stroke={1.8} />,
        hint: !topCurrency
          ? "No events carried an amount"
          : otherCurrencies.length
            ? `plus ${otherCurrencies
              .map((r) => fmtMoney(r.revenue, r.currency))
              .join(" · ")} — not converted`
            : `across ${fmtInt(topCurrency.events)} events`,
      },
    ];
  }, [series, summary]);

  return (
    <Stack gap="sm">
      {/* A capped scan must announce itself — otherwise partial figures read as
          the whole picture. */}
      {summary?.truncated && (
        <Alert
          color="yellow"
          icon={<IconAlertTriangle size={18} />}
          title="Showing partial data"
        >
          Only the first {fmtInt(summary.scannedDocs)} matching events were read.
          Narrow the date range or add filters for complete figures.
        </Alert>
      )}

      <StatTiles tiles={tiles} loading={loading && !summary} />
    </Stack>
  );
}
