/**
 * JailDistributionChart — horizontal bar chart showing ban counts per jail,
 * sorted descending, for the selected time window.
 *
 * Calls `useJailDistribution` internally and handles loading, error, and
 * empty states so the parent only needs to pass filter props.
 */

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

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

/** Maximum characters before truncating a jail name on the Y-axis. */
const MAX_LABEL_LENGTH = 24;

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

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

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

/** Props for {@link JailDistributionChart}. */
interface JailDistributionChartProps {
  /** Time-range preset controlling the query window. */
  timeRange: TimeRange;
  /** Origin filter controlling which bans are included. */
  origin: BanOriginFilter;
}

/** Internal chart data point shape. */
interface BarEntry {
  /** Full jail 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 = 160;

const useStyles = makeStyles({
  wrapper: {
    width: "100%",
    overflowX: "hidden",
  },
});

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

/**
 * Build the chart dataset from the raw jail list.
 *
 * @param jails - Ordered list of `{jail, count}` items from the API.
 * @returns Array of `BarEntry` objects ready for Recharts.
 */
function buildEntries(jails: Array<{ jail: string; count: number }>): BarEntry[] {
  return jails.map(({ jail, count }) => ({
    fullName: jail,
    name: jail.length > MAX_LABEL_LENGTH ? `${jail.slice(0, MAX_LABEL_LENGTH)}…` : jail,
    value: count,
  }));
}

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

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

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

/**
 * Horizontal bar chart showing ban counts per jail for the selected window.
 *
 * Fetches data via `useJailDistribution` and renders loading, error, and
 * empty states inline.
 *
 * @param props - `timeRange` and `origin` filter props.
 */
export function JailDistributionChart({
  timeRange,
  origin,
}: JailDistributionChartProps): React.JSX.Element {
  const styles = useStyles();
  const { jails, isLoading, error, reload } = useJailDistribution(timeRange, origin);

  const entries = buildEntries(jails);
  const chartHeight = Math.max(entries.length * BAR_HEIGHT_PX, MIN_CHART_HEIGHT);
  const { primaryColour, axisColour, gridColour } = useMemo(
    () => ({
      primaryColour: resolveFluentToken(CHART_PALETTE[0] ?? ""),
      axisColour: resolveFluentToken(CHART_AXIS_TEXT_TOKEN),
      gridColour: resolveFluentToken(CHART_GRID_LINE_TOKEN),
    }),
    [],
  );

  return (
    <ChartStateWrapper
      isLoading={isLoading}
      error={error}
      onRetry={reload}
      isEmpty={jails.length === 0}
      emptyMessage="No bans in this time range."
      minHeight={MIN_CHART_HEIGHT}
    >
      <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={JailTooltip} cursor={{ fill: "transparent" }} />
            <Bar dataKey="value" fill={primaryColour} radius={[0, 3, 3, 0]} />
          </BarChart>
        </ResponsiveContainer>
      </div>
    </ChartStateWrapper>
  );
}
