/**
 * TopCountriesBarChart — horizontal bar chart showing the top 20 countries
 * by ban count, sorted descending.
 */

import { useMemo } from "react";
import {
  Bar,
  BarChart,
  CartesianGrid,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import type { TooltipContentProps } from "recharts/types/component/Tooltip";
import { tokens, makeStyles, Text } from "@fluentui/react-components";
import {
  CHART_PALETTE,
  CHART_AXIS_TEXT_TOKEN,
  CHART_GRID_LINE_TOKEN,
  resolveFluentToken,
} from "../utils/chartTheme";
import { ChartTooltip } from "./ChartTooltip";

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

const TOP_N = 20;

/** Maximum chars before truncating a country name on the Y-axis. */
const MAX_LABEL_LENGTH = 20;

/** Height per bar row in pixels. */
const BAR_HEIGHT_PX = 36;

/** Minimum chart height in pixels. */
const MIN_CHART_HEIGHT = 180;

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

interface TopCountriesBarChartProps {
  /** 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 BarEntry {
  /** Full country name used by Tooltip. */
  fullName: string;
  /** Truncated name displayed on the Y-axis. */
  name: string;
  /** Ban count. */
  value: number;
}

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

const CHART_TICK_FONT_SIZE = 12;
const CHART_MARGIN = { top: 4, right: 16, bottom: 4, left: 8 };
const Y_AXIS_WIDTH = 140;

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

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

/** Build the sorted top-N dataset from raw country maps. */
function buildEntries(
  countries: Record<string, number>,
  countryNames: Record<string, string>,
): BarEntry[] {
  return Object.entries(countries)
    .sort(([, a], [, b]) => b - a)
    .slice(0, TOP_N)
    .map(([code, count]) => {
      const full = countryNames[code] ?? code;
      return {
        fullName: full,
        name:
          full.length > MAX_LABEL_LENGTH
            ? `${full.slice(0, MAX_LABEL_LENGTH)}…`
            : full,
        value: count,
      };
    });
}

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

function BarTooltip(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 fullName = (entry.payload as BarEntry).fullName;
  return (
    <ChartTooltip active={active}>
      <strong>{fullName}</strong>
      <br />
      {String(entry.value)} ban{entry.value === 1 ? "" : "s"}
    </ChartTooltip>
  );
}

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

/**
 * Horizontal bar chart showing the top 20 countries by ban count.
 *
 * @param props - `countries` map and `countryNames` map from the
 *   `/api/dashboard/bans/by-country` response.
 */
export function TopCountriesBarChart({
  countries,
  countryNames,
}: TopCountriesBarChartProps): React.JSX.Element {
  const styles = useStyles();

  const entries = buildEntries(countries, countryNames);

  const { primaryColour, axisColour, gridColour } = useMemo(
    () => ({
      primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
      axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
      gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
    }),
    [],
  );

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

  const chartHeight = Math.max(entries.length * BAR_HEIGHT_PX, MIN_CHART_HEIGHT);

  return (
    <div className={styles.wrapper} style={{ height: chartHeight }}>
      <ResponsiveContainer width="100%" height="100%">
        <BarChart
          layout="vertical"
          data={entries}
          margin={CHART_MARGIN}
        >
          <CartesianGrid strokeDasharray="3 3" stroke={gridColour} horizontal={false} />
          <XAxis
            type="number"
            tick={{ fill: axisColour, fontSize: CHART_TICK_FONT_SIZE }}
            axisLine={{ stroke: gridColour }}
            tickLine={false}
          />
          <YAxis
            type="category"
            dataKey="name"
            width={Y_AXIS_WIDTH}
            tick={{ fill: axisColour, fontSize: CHART_TICK_FONT_SIZE }}
            axisLine={false}
            tickLine={false}
          />
          <Tooltip content={BarTooltip} cursor={{ fill: "transparent" }} />
          <Bar dataKey="value" fill={primaryColour} radius={[0, 3, 3, 0]} />
        </BarChart>
      </ResponsiveContainer>
    </div>
  );
}
