/**
 * 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 {
  Bar,
  BarChart,
  CartesianGrid,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import type { TooltipContentProps } from "recharts/types/component/Tooltip";
import {
  MessageBar,
  MessageBarBody,
  Spinner,
  Text,
  tokens,
  makeStyles,
} from "@fluentui/react-components";
import {
  CHART_AXIS_TEXT_TOKEN,
  CHART_GRID_LINE_TOKEN,
  CHART_PALETTE,
  resolveFluentToken,
} from "../utils/chartTheme";
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 useStyles = makeStyles({
  wrapper: {
    width: "100%",
    overflowX: "hidden",
  },
  stateWrapper: {
    width: "100%",
    minHeight: `${String(MIN_CHART_HEIGHT)}px`,
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  emptyText: {
    color: tokens.colorNeutralForeground3,
  },
});

// ---------------------------------------------------------------------------
// 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 (
    <div
      style={{
        backgroundColor: resolveFluentToken(tokens.colorNeutralBackground1),
        border: `1px solid ${resolveFluentToken(tokens.colorNeutralStroke2)}`,
        borderRadius: "4px",
        padding: "8px 12px",
        color: resolveFluentToken(tokens.colorNeutralForeground1),
        fontSize: "13px",
      }}
    >
      <strong>{fullName}</strong>
      <br />
      {String(value)} ban{value === 1 ? "" : "s"}
    </div>
  );
}

// ---------------------------------------------------------------------------
// 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 } = useJailDistribution(timeRange, origin);

  if (error != null) {
    return (
      <MessageBar intent="error">
        <MessageBarBody>{error}</MessageBarBody>
      </MessageBar>
    );
  }

  if (isLoading) {
    return (
      <div className={styles.stateWrapper}>
        <Spinner label="Loading chart data…" />
      </div>
    );
  }

  if (jails.length === 0) {
    return (
      <div className={styles.stateWrapper}>
        <Text className={styles.emptyText}>No ban data for the selected period.</Text>
      </div>
    );
  }

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

  const primaryColour = resolveFluentToken(CHART_PALETTE[0] ?? "");
  const axisColour = resolveFluentToken(CHART_AXIS_TEXT_TOKEN);
  const gridColour = resolveFluentToken(CHART_GRID_LINE_TOKEN);

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