/**
 * Left sidebar controls for the graph view (R3.5.2).
 *
 * Contains: space filter, edge-type checkboxes, depth slider,
 * include-orphans toggle, page search autocomplete, reset button,
 * and graph stats display.
 */

import {
  Stack,
  Text,
  Slider,
  Checkbox,
  Switch,
  Button,
  TextInput,
  Divider,
  Badge,
  Group,
  Alert,
  Select,
  Paper,
} from "@mantine/core";
import { IconSearch, IconRefresh, IconAlertTriangle } from "@tabler/icons-react";
import { useTranslation } from "react-i18next";
import { useMemo } from "react";
import { GraphNode, GraphMeta } from "../services/graph-client";
import {
  GraphFilters,
  EdgeType,
  useGraphFilters,
} from "../hooks/use-graph-controls";

const EDGE_TYPE_OPTIONS: Array<{ value: EdgeType; labelKey: string; color: string }> = [
  { value: "wikilink", labelKey: "graph.edge_type_wikilink", color: "blue" },
  { value: "mention", labelKey: "graph.edge_type_mention", color: "green" },
  {
    value: "database_embed",
    labelKey: "graph.edge_type_database_embed",
    color: "orange",
  },
];

interface GraphControlsProps {
  nodes: GraphNode[];
  meta: GraphMeta | null;
  onSearchChange: (term: string) => void;
  searchTerm: string;
}

export function GraphControls({
  nodes,
  meta,
  onSearchChange,
  searchTerm,
}: GraphControlsProps) {
  const { t } = useTranslation();
  const [filters, setFilters] = useGraphFilters();

  const spaceOptions = useMemo(() => {
    const seen = new Map<string, string>();
    for (const n of nodes) {
      if (!seen.has(n.spaceId)) {
        seen.set(n.spaceId, n.spaceName ?? n.spaceId);
      }
    }
    return [
      { value: "", label: t("graph.all_spaces") },
      ...Array.from(seen.entries()).map(([id, name]) => ({
        value: id,
        label: name,
      })),
    ];
  }, [nodes, t]);

  function update(partial: Partial<GraphFilters>) {
    setFilters((prev) => ({ ...prev, ...partial }));
  }

  function resetFilters() {
    setFilters({
      depth: 2,
      edgeTypes: ["wikilink", "mention", "database_embed"],
      includeOrphans: false,
      spaceId: null,
      searchTerm: "",
    });
    onSearchChange("");
  }

  function toggleEdgeType(type: EdgeType, checked: boolean) {
    if (checked) {
      update({ edgeTypes: [...filters.edgeTypes, type] });
    } else {
      update({ edgeTypes: filters.edgeTypes.filter((t) => t !== type) });
    }
  }

  return (
    <Paper
      shadow="xs"
      p="md"
      radius={0}
      style={{
        width: 240,
        minWidth: 240,
        maxWidth: 240,
        height: "100%",
        overflowY: "auto",
        borderRight: "1px solid var(--mantine-color-default-border)",
      }}
    >
      <Stack gap="md">
        <TextInput
          leftSection={<IconSearch size={14} />}
          placeholder={t("graph.search_placeholder")}
          value={searchTerm}
          onChange={(e) => onSearchChange(e.currentTarget.value)}
          size="sm"
          aria-label={t("graph.search_placeholder")}
        />

        <Divider label={t("graph.filters_label")} labelPosition="center" />

        <Select
          label={t("graph.space_filter_label")}
          data={spaceOptions}
          value={filters.spaceId ?? ""}
          onChange={(val) => update({ spaceId: val || null })}
          size="xs"
          clearable={false}
        />

        <div>
          <Text size="xs" fw={500} mb={6}>
            {t("graph.edge_types_label")}
          </Text>
          <Stack gap={4}>
            {EDGE_TYPE_OPTIONS.map(({ value, labelKey, color }) => (
              <Checkbox
                key={value}
                size="xs"
                label={
                  <Badge size="xs" color={color} variant="light">
                    {t(labelKey)}
                  </Badge>
                }
                checked={filters.edgeTypes.includes(value)}
                onChange={(e) => toggleEdgeType(value, e.currentTarget.checked)}
              />
            ))}
          </Stack>
        </div>

        <div>
          <Text size="xs" fw={500} mb={6}>
            {t("graph.depth_label", { depth: filters.depth })}
          </Text>
          <Slider
            min={1}
            max={5}
            step={1}
            value={filters.depth}
            onChange={(val) => update({ depth: val })}
            marks={[1, 2, 3, 4, 5].map((v) => ({ value: v, label: String(v) }))}
            size="xs"
            aria-label={t("graph.depth_label", { depth: filters.depth })}
          />
        </div>

        <Switch
          size="xs"
          label={t("graph.include_orphans_label")}
          checked={filters.includeOrphans}
          onChange={(e) => update({ includeOrphans: e.currentTarget.checked })}
        />

        {meta && (
          <>
            <Divider label={t("graph.stats_label")} labelPosition="center" />
            <Group gap="xs">
              <Badge size="xs" variant="outline">
                {meta.totalNodes} {t("graph.nodes_unit")}
              </Badge>
              <Badge size="xs" variant="outline">
                {meta.totalEdges} {t("graph.edges_unit")}
              </Badge>
            </Group>
            {meta.truncated && (
              <Alert
                icon={<IconAlertTriangle size={14} />}
                color="yellow"
                variant="light"
                p="xs"
              >
                <Text size="xs">{t("graph.truncated_warning")}</Text>
              </Alert>
            )}
          </>
        )}

        <Button
          size="xs"
          variant="subtle"
          leftSection={<IconRefresh size={14} />}
          onClick={resetFilters}
          fullWidth
        >
          {t("graph.reset_filters")}
        </Button>
      </Stack>
    </Paper>
  );
}
