/**
 * TopCountriesPieChart — shows the top 4 countries by ban count plus
 * an "Other" slice aggregating all remaining countries.
 */

import { memo, useMemo } from "react";
import {
  Cell,
  Legend,
  Pie,
  PieChart,
  ResponsiveContainer,
  Tooltip,
} from "recharts";
import type { PieLabelRenderProps } from "recharts";
import type { LegendPayload } from "recharts/types/component/DefaultLegendContent";
import type { TooltipContentProps } from "recharts/types/component/Tooltip";
import { tokens, makeStyles, Text } from "@fluentui/react-components";
import { CHART_PALETTE, resolveFluentToken } from "../utils/chartTheme";
import { useThemeMode } from "../providers/ThemeProvider";
import { ChartTooltip } from "./ChartTooltip";

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const TOP_N = 4;
const OTHER_LABEL = "Other";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface TopCountriesPieChartProps {
  /** ISO alpha-2 country code → ban count. */
  countries: Record<string, number>;
  /** ISO alpha-2 country code → human-readable country name. */
  countryNames: Record<string, string>;
}

interface SliceData {
  name: string;
  value: number;
  /** Resolved fill colour for this slice. */
  fill: string;
}

// ---------------------------------------------------------------------------
// Styles
// ---------------------------------------------------------------------------

const useStyles = makeStyles({
  wrapper: {
    width: "100%",
    minHeight: "280px",
  },
  emptyWrapper: {
    width: "100%",
    minHeight: "280px",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  emptyText: {
    color: tokens.colorNeutralForeground3,
  },
});

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

/** Build the 5-slice dataset from raw country maps, with resolved colours. */
function buildSlices(
  countries: Record<string, number>,
  countryNames: Record<string, string>,
  palette: readonly string[],
): SliceData[] {
  const entries = Object.entries(countries).sort(([, a], [, b]) => b - a);
  const top = entries.slice(0, TOP_N);
  const rest = entries.slice(TOP_N);

  const slices: SliceData[] = top.map(([code, count], index) => ({
    name: countryNames[code] ?? code,
    value: count,
    fill: palette[index % palette.length] ?? "",
  }));

  if (rest.length > 0) {
    const otherTotal = rest.reduce((sum, [, c]) => sum + c, 0);
    slices.push({
      name: OTHER_LABEL,
      value: otherTotal,
      fill: palette[slices.length % palette.length] ?? "",
    });
  }

  return slices;
}

// ---------------------------------------------------------------------------
// Custom tooltip
// ---------------------------------------------------------------------------

function PieTooltip(props: TooltipContentProps): React.JSX.Element | null {
  const { active, payload } = props;
  if (!active || payload.length === 0) return null;
  const entry = payload[0];
  if (entry == null) return null;
  const banCount = entry.value;
  const displayName: string = entry.name?.toString() ?? "";
  return (
    <ChartTooltip active={active}>
      <strong>{displayName}</strong>
      <br />
      {banCount != null
        ? `${String(banCount)} ban${banCount === 1 ? "" : "s"}`
        : ""}
    </ChartTooltip>
  );
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

/**
 * Pie chart showing the top 4 countries by ban count plus an "Other" slice.
 *
 * @param props - `countries` map and `countryNames` map from the
 *   `/api/dashboard/bans/by-country` response.
 */
export const TopCountriesPieChart = memo(function TopCountriesPieChart({
  countries,
  countryNames,
}: TopCountriesPieChartProps): React.JSX.Element {
  const styles = useStyles();
  const { colorMode } = useThemeMode();

  const resolvedPalette = useMemo(
    () => {
      void colorMode;
      return CHART_PALETTE.map(resolveFluentToken);
    },
    [colorMode],
  );
  const slices = buildSlices(countries, countryNames, resolvedPalette);
  const total = slices.reduce((sum, s) => sum + s.value, 0);

  if (slices.length === 0) {
    return (
      <div className={styles.emptyWrapper}>
        <Text className={styles.emptyText}>No bans in this time range.</Text>
      </div>
    );
  }

  /** Format legend entries as "Country Name (xx%)" and colour them to match their slice. */
  const legendFormatter = (
    value: string,
    entry: LegendPayload,
  ): React.ReactNode => {
    const slice = slices.find((s) => s.name === value);
    if (slice == null || total === 0) return value;
    const pct = ((slice.value / total) * 100).toFixed(1);
    return (
      <span style={{ color: entry.color }}>
        {value} ({pct}%)
      </span>
    );
  };

  return (
    <div className={styles.wrapper}>
      <ResponsiveContainer width="100%" height={280}>
        <PieChart>
          <Pie
            data={slices}
            dataKey="value"
            nameKey="name"
            cx="50%"
            cy="50%"
            outerRadius={90}
            label={(labelProps: PieLabelRenderProps): string => {
              const name = labelProps.name ?? "";
              const percent = labelProps.percent ?? 0;
              return `${name}: ${(percent * 100).toFixed(0)}%`;
            }}
            labelLine={false}
          >
            {slices.map((slice) => (
              // eslint-disable-next-line @typescript-eslint/no-deprecated
              <Cell key={slice.name} fill={slice.fill} />
            ))}
          </Pie>
          <Tooltip content={PieTooltip} />
          <Legend formatter={legendFormatter} />
        </PieChart>
      </ResponsiveContainer>
    </div>
  );
});
