/**
 * HistoryPage — forensic exploration of all historical fail2ban ban records.
 *
 * Shows a paginated, filterable table of every ban ever recorded in the
 * fail2ban database.  Clicking an IP address opens a per-IP timeline view.
 * Rows with repeatedly-banned IPs are highlighted in amber.
 */

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import {
  Badge,
  Button,
  DataGrid,
  DataGridBody,
  DataGridCell,
  DataGridHeader,
  DataGridHeaderCell,
  DataGridRow,
  Text,
  Toolbar,
  ToolbarButton,
  createTableColumn,
  makeStyles,
  tokens,
} from "@fluentui/react-components";
import type { TableColumnDefinition } from "@fluentui/react-components";
import {
  ArrowCounterclockwiseRegular,
  ChevronLeftRegular,
  ChevronRightRegular,
} from "@fluentui/react-icons";
import { DashboardFilterBar } from "../components/DashboardFilterBar";
import { useHistory } from "../hooks/useHistory";
import { IpDetailView } from "./history/IpDetailView";
import { areHistoryQueriesEqual } from "../utils/queryUtils";
import type { HistoryBanItem, HistoryQuery, TimeRange } from "../types/history";
import type { BanOriginFilter } from "../types/ban";

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

/** Ban counts at or above this threshold are highlighted. */
const HIGH_BAN_THRESHOLD = 5;

const PAGE_SIZE = 50;

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

const useStyles = makeStyles({
  root: {
    display: "flex",
    flexDirection: "column",
    gap: tokens.spacingVerticalL,
    padding: tokens.spacingVerticalXXL,
    paddingLeft: tokens.spacingHorizontalXXL,
    paddingRight: tokens.spacingHorizontalXXL,
  },
  header: {
    display: "flex",
    alignItems: "center",
    justifyContent: "space-between",
    flexWrap: "wrap",
    gap: tokens.spacingHorizontalM,
  },
  filterRow: {
    display: "flex",
    alignItems: "flex-end",
    gap: tokens.spacingHorizontalM,
    flexWrap: "wrap",
  },
  tableWrapper: {
    overflow: "auto",
    borderRadius: tokens.borderRadiusMedium,
    border: `1px solid ${tokens.colorNeutralStroke1}`,
  },
  ipCell: {
    fontFamily: "Consolas, 'Courier New', monospace",
    fontSize: "0.85rem",
    color: tokens.colorBrandForeground1,
    cursor: "pointer",
    textDecoration: "underline",
  },
  highBanRow: {
    backgroundColor: tokens.colorPaletteYellowBackground1,
  },
  pagination: {
    display: "flex",
    alignItems: "center",
    gap: tokens.spacingHorizontalM,
    justifyContent: "flex-end",
  },
  detailGrid: {
    display: "grid",
    gridTemplateColumns: "repeat(auto-fit, minmax(160px, 1fr))",
    gap: tokens.spacingVerticalM,
    padding: tokens.spacingVerticalM,
    marginBottom: tokens.spacingVerticalM,
  },
  detailField: {
    display: "flex",
    flexDirection: "column",
    gap: tokens.spacingVerticalXS,
  },
  detailLabel: {
    color: tokens.colorNeutralForeground3,
    fontSize: "0.75rem",
    textTransform: "uppercase",
    letterSpacing: "0.05em",
  },
  detailValue: {
    fontSize: "0.9rem",
    fontWeight: "600",
  },
  monoText: {
    fontFamily: "Consolas, 'Courier New', monospace",
    fontSize: "0.85rem",
  },
});

// ---------------------------------------------------------------------------
// Column definitions for the main history table
// ---------------------------------------------------------------------------

const HISTORY_COLUMNS = (
  onClickIp: (ip: string) => void,
  styles: ReturnType<typeof useStyles>,
): TableColumnDefinition<HistoryBanItem>[] =>
  [
    createTableColumn<HistoryBanItem>({
      columnId: "banned_at",
      renderHeaderCell: () => "Banned At",
      renderCell: (item) => (
        <Text size={200}>{new Date(item.banned_at).toLocaleString()}</Text>
      ),
    }),
    createTableColumn<HistoryBanItem>({
      columnId: "ip",
      renderHeaderCell: () => "IP Address",
      renderCell: (item) => (
        <span
          className={styles.ipCell}
          role="button"
          tabIndex={0}
          onClick={(): void => {
            onClickIp(item.ip);
          }}
          onKeyDown={(e): void => {
            if (e.key === "Enter" || e.key === " ") onClickIp(item.ip);
          }}
        >
          {item.ip}
        </span>
      ),
    }),
    createTableColumn<HistoryBanItem>({
      columnId: "jail",
      renderHeaderCell: () => "Jail",
      renderCell: (item) => <Text size={200}>{item.jail}</Text>,
    }),
    createTableColumn<HistoryBanItem>({
      columnId: "country",
      renderHeaderCell: () => "Country",
      renderCell: (item) => (
        <Text size={200}>{item.country_name ?? item.country_code ?? "—"}</Text>
      ),
    }),
    createTableColumn<HistoryBanItem>({
      columnId: "failures",
      renderHeaderCell: () => "Failures",
      renderCell: (item) => <Text size={200}>{String(item.failures)}</Text>,
    }),
    createTableColumn<HistoryBanItem>({
      columnId: "ban_count",
      renderHeaderCell: () => "Times Banned",
      renderCell: (item) => (
        <Badge
          appearance="filled"
          color={item.ban_count >= HIGH_BAN_THRESHOLD ? "danger" : "subtle"}
          size="medium"
        >
          {String(item.ban_count)}
        </Badge>
      ),
    }),
  ] as ReturnType<typeof createTableColumn<HistoryBanItem>>[];

// ---------------------------------------------------------------------------
// HistoryPage — main component
// ---------------------------------------------------------------------------

export function HistoryPage(): React.JSX.Element {
  const styles = useStyles();

  // Filter state
  const [range, setRange] = useState<TimeRange>("7d");
  const [originFilter, setOriginFilter] = useState<BanOriginFilter>("all");
  const [jailFilter, setJailFilter] = useState("");
  const [ipFilter, setIpFilter] = useState("");
  const defaultQuery: HistoryQuery = {
    range: "7d",
    source: "archive",
    page_size: PAGE_SIZE,
    page: 1,
  };
  const [appliedQuery, setAppliedQuery] = useState<HistoryQuery>(defaultQuery);
  const appliedQueryRef = useRef<HistoryQuery>(defaultQuery);

  // Per-IP detail navigation
  const [selectedIp, setSelectedIp] = useState<string | null>(null);

  const { items, total, page, loading, error, setPage, refresh } =
    useHistory(appliedQuery);

  const handleIpClick = useCallback((ip: string): void => {
    setSelectedIp(ip);
  }, []);

  const columns = useMemo(
    () => HISTORY_COLUMNS(handleIpClick, styles),
    [handleIpClick, styles],
  );

  useEffect((): void => {
    const nextQuery: HistoryQuery = {
      range,
      origin: originFilter !== "all" ? originFilter : undefined,
      jail: jailFilter.trim() || undefined,
      ip: ipFilter.trim() || undefined,
      source: "archive",
      page: 1,
      page_size: PAGE_SIZE,
    };

    if (areHistoryQueriesEqual(nextQuery, appliedQueryRef.current)) {
      return;
    }

    setPage(1);
    setAppliedQuery(nextQuery);
    appliedQueryRef.current = nextQuery;
  }, [range, originFilter, jailFilter, ipFilter, setPage]);

  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));

  // If an IP is selected, show the detail view.
  if (selectedIp !== null) {
    return (
      <div className={styles.root}>
        <IpDetailView
          ip={selectedIp}
          onBack={(): void => {
            setSelectedIp(null);
          }}
        />
      </div>
    );
  }

  return (
    <div className={styles.root}>
      {/* ---------------------------------------------------------------- */}
      {/* Header                                                            */}
      {/* ---------------------------------------------------------------- */}
      <div className={styles.header}>
        <Text as="h1" size={700} weight="semibold">
          History
        </Text>
        <Toolbar size="small">
          <ToolbarButton
            icon={<ArrowCounterclockwiseRegular />}
            onClick={(): void => {
              refresh();
            }}
            disabled={loading}
            title="Refresh"
          />
        </Toolbar>
      </div>

      {/* ---------------------------------------------------------------- */}
      {/* Filter bar                                                        */}
      {/* ---------------------------------------------------------------- */}
      <div className={styles.filterRow}>
        <DashboardFilterBar
          timeRange={range}
          onTimeRangeChange={(value) => {
            setRange(value);
          }}
          originFilter={originFilter}
          onOriginFilterChange={(value) => {
            setOriginFilter(value);
          }}
          jail={jailFilter}
          onJailChange={(value) => {
            setJailFilter(value);
          }}
          ip={ipFilter}
          onIpChange={(value) => {
            setIpFilter(value);
          }}
        />
      </div>

      {/* ---------------------------------------------------------------- */}
      {/* Summary                                                           */}
      {/* ---------------------------------------------------------------- */}
      {!loading && !error && (
        <Text size={300} style={{ color: tokens.colorNeutralForeground3 }}>
          {String(total)} record{total !== 1 ? "s" : ""} found ·
          Page {String(page)} of {String(totalPages)} ·
          Rows highlighted in yellow have {String(HIGH_BAN_THRESHOLD)}+ repeat bans
        </Text>
      )}

      {/* ---------------------------------------------------------------- */}
      {/* DataGrid table                                                    */}
      {/* ---------------------------------------------------------------- */}
      {!loading && !error && (
        <div className={styles.tableWrapper}>
          <DataGrid
            items={items}
            columns={columns}
            getRowId={(item: HistoryBanItem) => `${item.ip}-${item.banned_at}`}
            focusMode="composite"
          >
            <DataGridHeader>
              <DataGridRow>
                {({ renderHeaderCell }) => (
                  <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
                )}
              </DataGridRow>
            </DataGridHeader>
            <DataGridBody<HistoryBanItem>>
              {({ item }) => (
                <DataGridRow<HistoryBanItem>
                  key={`${item.ip}-${item.banned_at}`}
                  className={
                    item.ban_count >= HIGH_BAN_THRESHOLD
                      ? styles.highBanRow
                      : undefined
                  }
                >
                  {({ renderCell }) => (
                    <DataGridCell>{renderCell(item)}</DataGridCell>
                  )}
                </DataGridRow>
              )}
            </DataGridBody>
          </DataGrid>
        </div>
      )}

      {/* ---------------------------------------------------------------- */}
      {/* Pagination                                                        */}
      {/* ---------------------------------------------------------------- */}
      {!loading && !error && totalPages > 1 && (
        <div className={styles.pagination}>
          <Button
            icon={<ChevronLeftRegular />}
            appearance="subtle"
            size="small"
            disabled={page <= 1}
            onClick={(): void => {
              setPage(page - 1);
            }}
          />
          <Text size={200}>
            Page {String(page)} / {String(totalPages)}
          </Text>
          <Button
            icon={<ChevronRightRegular />}
            appearance="subtle"
            size="small"
            disabled={page >= totalPages}
            onClick={(): void => {
              setPage(page + 1);
            }}
          />
        </div>
      )}
    </div>
  );
}
