/**
 * `BanTable` component.
 *
 * Renders a Fluent UI v9 `DataGrid` for the dashboard ban-list view.
 * Uses the {@link useBans} hook to fetch and manage paginated data from
 * the backend.
 *
 * Columns: Time, IP, Service, Country, Jail, Ban Count.
 */

import { useMemo } from "react";
import {
  Badge,
  Button,
  DataGrid,
  DataGridBody,
  DataGridCell,
  DataGridHeader,
  DataGridHeaderCell,
  DataGridRow,
  Text,
  Tooltip,
  makeStyles,
  tokens,
  type TableColumnDefinition,
  createTableColumn,
} from "@fluentui/react-components";
import { PageEmpty, PageError, PageLoading } from "./PageFeedback";
import { ChevronLeftRegular, ChevronRightRegular } from "@fluentui/react-icons";
import { useBans } from "../hooks/useBans";
import { formatTimestamp } from "../utils/formatDate";
import type { DashboardBanItem, TimeRange, BanOriginFilter } from "../types/ban";

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

/** Props for the {@link BanTable} component. */
interface BanTableProps {
  /**
   * Active time-range preset — controlled by the parent `DashboardPage`.
   * Changing this value triggers a re-fetch.
   */
  timeRange: TimeRange;
  /**
   * Active origin filter — controlled by the parent `DashboardPage`.
   * Changing this value triggers a re-fetch and resets to page 1.
   */
  origin?: BanOriginFilter;
  /**
   * Data source used for the table query.
   */
  source?: "fail2ban" | "archive";
}

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

const useStyles = makeStyles({
  root: {
    display: "flex",
    flexDirection: "column",
    gap: tokens.spacingVerticalS,
    minHeight: "300px",
  },
  centred: {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    padding: tokens.spacingVerticalXXL,
  },
  tableWrapper: {
    overflowX: "auto",
  },
  pagination: {
    display: "flex",
    alignItems: "center",
    justifyContent: "flex-end",
    gap: tokens.spacingHorizontalS,
    paddingTop: tokens.spacingVerticalS,
  },
  mono: {
    fontFamily: "Consolas, 'Courier New', monospace",
    fontSize: tokens.fontSizeBase200,
  },
  truncate: {
    overflow: "hidden",
    textOverflow: "ellipsis",
    whiteSpace: "nowrap",
    maxWidth: "280px",
    display: "inline-block",
  },
  countBadge: {
    fontVariantNumeric: "tabular-nums",
  },
});

// ---------------------------------------------------------------------------
// Column definitions
// ---------------------------------------------------------------------------

/** Columns for the ban-list view (`mode === "bans"`). */
function buildBanColumns(styles: ReturnType<typeof useStyles>): TableColumnDefinition<DashboardBanItem>[] {
  return [
    createTableColumn<DashboardBanItem>({
      columnId: "banned_at",
      renderHeaderCell: () => "Time of Ban",
      renderCell: (item) => (
        <Text size={200}>{formatTimestamp(item.banned_at)}</Text>
      ),
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "ip",
      renderHeaderCell: () => "IP Address",
      renderCell: (item) => (
        <span className={styles.mono}>{item.ip}</span>
      ),
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "service",
      renderHeaderCell: () => "Service / URL",
      renderCell: (item) =>
        item.service ? (
          <Tooltip content={item.service} relationship="description">
            <span className={`${styles.mono} ${styles.truncate}`}>{item.service}</span>
          </Tooltip>
        ) : (
          <Text size={200} style={{ color: tokens.colorNeutralForeground3 }}>
            —
          </Text>
        ),
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "country",
      renderHeaderCell: () => "Country",
      renderCell: (item) =>
        item.country_name ?? item.country_code ? (
          <Text size={200}>{item.country_name ?? item.country_code}</Text>
        ) : (
          <Tooltip
            content="Country could not be resolved — will retry automatically."
            relationship="description"
          >
            <Text size={200} style={{ color: tokens.colorNeutralForeground3 }}>
              —
            </Text>
          </Tooltip>
        ),
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "jail",
      renderHeaderCell: () => "Jail",
      renderCell: (item) => <Text size={200}>{item.jail}</Text>,
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "origin",
      renderHeaderCell: () => "Origin",
      renderCell: (item) => (
        <Badge
          appearance="tint"
          color={item.origin === "blocklist" ? "brand" : "informative"}
        >
          {item.origin === "blocklist" ? "Blocklist" : "Selfblock"}
        </Badge>
      ),
    }),
    createTableColumn<DashboardBanItem>({
      columnId: "ban_count",
      renderHeaderCell: () => "Bans",
      renderCell: (item) => (
        <Badge
          appearance={item.ban_count > 1 ? "filled" : "outline"}
          color={item.ban_count > 5 ? "danger" : item.ban_count > 1 ? "warning" : "informative"}
          className={styles.countBadge}
        >
          {item.ban_count}
        </Badge>
      ),
    }),
  ];
}

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

/**
 * Data table for the dashboard ban-list view.
 *
 * @param props.timeRange - Active time-range preset from the parent page.
 * @param props.origin    - Active origin filter from the parent page.
 */
export function BanTable({ timeRange, origin = "all", source = "fail2ban" }: BanTableProps): React.JSX.Element {
  const styles = useStyles();
  const { banItems, total, page, setPage, loading, error, refresh } = useBans(timeRange, origin, source);

  const banColumns = useMemo(() => buildBanColumns(styles), [styles]);

  // --------------------------------------------------------------------------
  // Loading state
  // --------------------------------------------------------------------------
  if (loading) {
    return <PageLoading label="Loading…" />;
  }

  // --------------------------------------------------------------------------
  // Error state
  // --------------------------------------------------------------------------
  if (error) {
    return <PageError message={error} onRetry={refresh} />;
  }

  // --------------------------------------------------------------------------
  // Empty state
  // --------------------------------------------------------------------------
  if (banItems.length === 0) {
    return <PageEmpty message="No bans recorded in the selected time window." />;
  }

  // --------------------------------------------------------------------------
  // Pagination helpers
  // --------------------------------------------------------------------------
  const pageSize = 100;
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
  const hasPrev = page > 1;
  const hasNext = page < totalPages;

  // --------------------------------------------------------------------------
  // Render
  // --------------------------------------------------------------------------
  return (
    <div className={styles.root}>
      <div className={styles.tableWrapper}>
        <DataGrid
          items={banItems}
          columns={banColumns}
          getRowId={(item: DashboardBanItem) => `${item.ip}:${item.jail}:${item.banned_at}`}
        >
          <DataGridHeader>
            <DataGridRow>
              {({ renderHeaderCell }) => (
                <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
              )}
            </DataGridRow>
          </DataGridHeader>
          <DataGridBody<DashboardBanItem>>
            {({ item, rowId }) => (
              <DataGridRow<DashboardBanItem> key={rowId}>
                {({ renderCell }) => (
                  <DataGridCell>{renderCell(item)}</DataGridCell>
                )}
              </DataGridRow>
            )}
          </DataGridBody>
        </DataGrid>
      </div>
      <div className={styles.pagination}>
        <Text size={200} style={{ color: tokens.colorNeutralForeground3 }}>
          {total} total · Page {page} of {totalPages}
        </Text>
        <Button
          icon={<ChevronLeftRegular />}
          appearance="subtle"
          disabled={!hasPrev}
          onClick={() => { setPage(page - 1); }}
          aria-label="Previous page"
        />
        <Button
          icon={<ChevronRightRegular />}
          appearance="subtle"
          disabled={!hasNext}
          onClick={() => { setPage(page + 1); }}
          aria-label="Next page"
        />
      </div>
    </div>
  );
}
