import {
  Anchor,
  Badge,
  Box,
  Button,
  Checkbox,
  Group,
  Image,
  Loader,
  Modal,
  Select,
  Stack,
  Text,
  TextInput,
  Tooltip,
} from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { IconBrandJira, IconRefresh, IconSearch } from "@tabler/icons-react";
import { useEffect, useMemo, useState } from "react";
import * as api from "../api";
import type { JiraIssue } from "../api";
import type { Column } from "../types";

interface Props {
  opened: boolean;
  onClose: () => void;
  columns: Column[];
  onImported?: () => void;
}

// ImportJiraModal lists every issue on the configured Jira board and lets the
// admin pick which ones to materialise as kanban cards. Issues already linked
// to a card are hidden by default and re-shown by toggling "Mostrar
// importadas". Each new card lands in the column whose status_map matches the
// issue's current status; the fallback column picker covers statuses without
// a mapping (e.g. Jira Backlog → kanban "HACIENDO").
export function ImportJiraModal({ opened, onClose, columns, onImported }: Props) {
  const [issues, setIssues] = useState<JiraIssue[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [importing, setImporting] = useState(false);
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [showImported, setShowImported] = useState(false);
  const [query, setQuery] = useState("");
  const [fallbackColumn, setFallbackColumn] = useState<string>("");
  const [boardId, setBoardId] = useState<number | null>(null);
  const [projectKey, setProjectKey] = useState<string>("");
  const [error, setError] = useState<string | null>(null);

  const reload = async () => {
    setLoading(true);
    setError(null);
    try {
      const r = await api.listJiraIssues({ includeImported: showImported, limit: 200 });
      setIssues(r.issues);
      setBoardId(r.board_id);
      setProjectKey(r.project_key);
      // Clear selection of any keys that disappeared from the new list.
      setSelected((prev) => {
        const validKeys = new Set(r.issues.map((i) => i.key));
        const next = new Set<string>();
        for (const k of prev) if (validKeys.has(k)) next.add(k);
        return next;
      });
    } catch (e) {
      setError((e as Error).message);
      setIssues([]);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (opened) reload();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [opened, showImported]);

  // Default the fallback column to the first board column (operator can change
  // it via the Select). We only set it once columns are available.
  useEffect(() => {
    if (!fallbackColumn && columns.length > 0) {
      const boardCol = columns.find((c) => c.location !== "sidebar") || columns[0];
      setFallbackColumn(boardCol.id);
    }
  }, [columns, fallbackColumn]);

  const visible = useMemo(() => {
    if (!issues) return [];
    const q = query.trim().toLowerCase();
    if (!q) return issues;
    return issues.filter(
      (i) =>
        i.key.toLowerCase().includes(q) ||
        i.summary.toLowerCase().includes(q) ||
        i.assignee.toLowerCase().includes(q) ||
        i.status_name.toLowerCase().includes(q),
    );
  }, [issues, query]);

  const toggle = (key: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(key)) next.delete(key);
      else next.add(key);
      return next;
    });
  };

  const toggleAll = () => {
    const importable = visible.filter((i) => !i.already_imported);
    if (selected.size === importable.length && importable.length > 0) {
      setSelected(new Set());
    } else {
      setSelected(new Set(importable.map((i) => i.key)));
    }
  };

  const doImport = async () => {
    if (selected.size === 0) return;
    setImporting(true);
    try {
      const res = await api.importJiraIssues(Array.from(selected), fallbackColumn || undefined);
      const ok = res.results.filter((r) => r.status === "imported").length;
      const skip = res.results.filter((r) => r.status === "skipped").length;
      const err = res.results.filter((r) => r.status === "error");
      const msg = `${ok} importadas` + (skip > 0 ? ` · ${skip} omitidas` : "") + (err.length > 0 ? ` · ${err.length} con error` : "");
      notifications.show({
        color: err.length > 0 ? "yellow" : "green",
        message: msg,
        autoClose: 5000,
      });
      if (err.length > 0) {
        console.warn("import errors", err);
      }
      setSelected(new Set());
      await reload();
      onImported?.();
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    } finally {
      setImporting(false);
    }
  };

  const columnOptions = columns.map((c) => ({ value: c.id, label: c.name }));

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      title={
        <Group gap={8}>
          <IconBrandJira size={18} />
          <Text fw={600}>
            Importar tareas de Jira{boardId ? ` · board ${boardId}` : ""}{projectKey ? ` (${projectKey})` : ""}
          </Text>
        </Group>
      }
      size="xl"
    >
      <Stack gap="sm">
        <Group gap="xs" wrap="nowrap">
          <TextInput
            placeholder="Filtrar por key, titulo, asignado o status..."
            value={query}
            onChange={(e) => setQuery(e.currentTarget.value)}
            leftSection={<IconSearch size={14} />}
            style={{ flex: 1 }}
          />
          <Tooltip label="Refrescar" withArrow>
            <Button variant="default" onClick={reload} loading={loading} leftSection={<IconRefresh size={14} />}>
              Refrescar
            </Button>
          </Tooltip>
        </Group>
        <Group justify="space-between" gap="xs">
          <Checkbox
            label="Mostrar issues ya importadas"
            checked={showImported}
            onChange={(e) => setShowImported(e.currentTarget.checked)}
          />
          <Select
            label="Columna fallback"
            description="Para issues cuyo status no tiene mapping"
            data={columnOptions}
            value={fallbackColumn}
            onChange={(v) => setFallbackColumn(v || "")}
            allowDeselect={false}
            w={260}
            size="xs"
          />
        </Group>

        {error && (
          <Text size="sm" c="red">{error}</Text>
        )}

        <Box style={{ maxHeight: 480, overflowY: "auto", border: "1px solid var(--mantine-color-default-border)", borderRadius: 4 }}>
          {loading && !issues ? (
            <Group justify="center" p="md"><Loader size="sm" /></Group>
          ) : visible.length === 0 ? (
            <Text size="sm" c="dimmed" p="md" ta="center">
              {issues?.length === 0
                ? "No hay issues sin importar en el board."
                : "Ninguna issue coincide con el filtro."}
            </Text>
          ) : (
            <Stack gap={0}>
              <Group
                p="xs"
                gap="xs"
                style={{ borderBottom: "1px solid var(--mantine-color-default-border)", background: "var(--mantine-color-default-hover)" }}
              >
                <Checkbox
                  checked={selected.size > 0 && selected.size === visible.filter((i) => !i.already_imported).length}
                  indeterminate={selected.size > 0 && selected.size < visible.filter((i) => !i.already_imported).length}
                  onChange={toggleAll}
                />
                <Text size="xs" fw={600} c="dimmed">
                  {visible.length} issues · {selected.size} seleccionadas
                </Text>
              </Group>
              {visible.map((iss) => (
                <Group
                  key={iss.key}
                  p="xs"
                  gap="xs"
                  wrap="nowrap"
                  style={{ borderBottom: "1px solid var(--mantine-color-default-border)", opacity: iss.already_imported ? 0.5 : 1 }}
                >
                  <Checkbox
                    checked={selected.has(iss.key)}
                    disabled={iss.already_imported}
                    onChange={() => toggle(iss.key)}
                  />
                  {iss.issue_type_icon && (
                    <Image src={iss.issue_type_icon} w={16} h={16} alt={iss.issue_type} />
                  )}
                  <Stack gap={2} style={{ flex: 1, minWidth: 0 }}>
                    <Group gap={6} wrap="nowrap">
                      <Anchor href={iss.url} target="_blank" rel="noopener noreferrer" size="sm" fw={600}>
                        {iss.key}
                      </Anchor>
                      <Text size="sm" truncate style={{ flex: 1 }}>{iss.summary}</Text>
                    </Group>
                    <Group gap={4} wrap="nowrap">
                      <Badge size="xs" variant="light" color={badgeColor(iss.status_name)}>{iss.status_name}</Badge>
                      <Badge size="xs" variant="outline">{iss.issue_type}</Badge>
                      {iss.assignee && <Text size="xs" c="dimmed">· {iss.assignee}</Text>}
                      {iss.already_imported && <Badge size="xs" color="gray">ya en kanban</Badge>}
                      {!iss.already_imported && !iss.mapped_column_id && (
                        <Badge size="xs" color="orange" variant="light">sin mapping (usa fallback)</Badge>
                      )}
                    </Group>
                  </Stack>
                </Group>
              ))}
            </Stack>
          )}
        </Box>

        <Group justify="flex-end" gap="xs">
          <Button variant="default" onClick={onClose} disabled={importing}>Cerrar</Button>
          <Button onClick={doImport} disabled={selected.size === 0 || importing} loading={importing}>
            Importar {selected.size > 0 ? `(${selected.size})` : ""}
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

function badgeColor(status: string): string {
  const s = status.toLowerCase();
  if (s.includes("done") || s.includes("hecho") || s.includes("closed")) return "green";
  if (s.includes("progress") || s.includes("doing")) return "blue";
  if (s.includes("implementado") || s.includes("review")) return "violet";
  if (s.includes("creado") || s.includes("backlog") || s.includes("nuevo")) return "gray";
  return "yellow";
}
