import {
  ActionIcon,
  Alert,
  Badge,
  Box,
  Button,
  Checkbox,
  Code,
  Divider,
  Group,
  JsonInput,
  Loader,
  Modal,
  ScrollArea,
  Select,
  Stack,
  Table,
  Tabs,
  Text,
  TextInput,
  Tooltip,
} from "@mantine/core";
import { notifications } from "@mantine/notifications";
import { IconPlug, IconPlugConnected, IconRefresh, IconTestPipe, IconTrash } from "@tabler/icons-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import * as api from "../api";
import type { KanbanModule, ModuleLog } from "../types";
import { formatDateTimeShort } from "./format";

interface Props {
  opened: boolean;
  onClose: () => void;
}

const KANBAN_EVENTS = [
  "card.created",
  "card.updated",
  "card.moved",
  "card.deleted",
  "message.created",
  "board.invalidated",
];

const DEFAULT_JIRA_CONFIG = {
  base_url: "",
  email: "",
  api_token: "",
  project_key: "",
  status_map: {
    "Por hacer": "To Do",
    "Doing": "In Progress",
    "Done": "Done",
  },
};

export function ModulesModal({ opened, onClose }: Props) {
  const [modules, setModules] = useState<KanbanModule[]>([]);
  const [loading, setLoading] = useState(false);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [editing, setEditing] = useState<KanbanModule | null>(null);
  const [logs, setLogs] = useState<ModuleLog[]>([]);
  const [logsLoading, setLogsLoading] = useState(false);
  const [activeTab, setActiveTab] = useState<string | null>("form");

  const reload = useCallback(async () => {
    setLoading(true);
    try {
      const list = await api.listModules();
      setModules(list);
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (opened) reload();
  }, [opened, reload]);

  const reloadLogs = useCallback(async (id: string) => {
    setLogsLoading(true);
    try {
      const out = await api.listModuleLogs(id);
      setLogs(out);
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    } finally {
      setLogsLoading(false);
    }
  }, []);

  const select = (m: KanbanModule | null) => {
    setEditing(m ? { ...m, config: { ...m.config } } : null);
    setSelectedId(m?.id ?? null);
    setActiveTab("form");
    setLogs([]);
    if (m) reloadLogs(m.id);
  };

  const startNew = () => {
    const blank: KanbanModule = {
      id: "",
      name: "Nuevo modulo",
      kind: "jira",
      enabled: false,
      event_filter: ["card.created", "card.updated", "card.moved", "message.created"],
      config: { ...DEFAULT_JIRA_CONFIG, status_map: { ...DEFAULT_JIRA_CONFIG.status_map } },
      created_at: "",
      updated_at: "",
    };
    setEditing(blank);
    setSelectedId(null);
    setActiveTab("form");
    setLogs([]);
  };

  const save = async () => {
    if (!editing) return;
    try {
      const payload = {
        name: editing.name,
        kind: editing.kind,
        enabled: editing.enabled,
        event_filter: editing.event_filter,
        config: editing.config,
      };
      const saved = editing.id
        ? await api.updateModule(editing.id, payload)
        : await api.createModule(payload);
      notifications.show({ color: "green", message: "Modulo guardado" });
      await reload();
      select(saved);
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    }
  };

  const remove = async () => {
    if (!selectedId) return;
    if (!confirm("Borrar modulo?")) return;
    try {
      await api.deleteModule(selectedId);
      notifications.show({ color: "green", message: "Modulo borrado" });
      setEditing(null);
      setSelectedId(null);
      reload();
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    }
  };

  const test = async () => {
    if (!editing) return;
    try {
      const result = editing.id
        ? await api.testModule(editing.id)
        : await api.testModule("draft", {
            name: editing.name,
            kind: editing.kind,
            enabled: editing.enabled,
            event_filter: editing.event_filter,
            config: editing.config,
          });
      if (result.ok) {
        notifications.show({
          color: "green",
          title: `Test OK (${result.status})`,
          message: `Conexion verificada en ${result.duration_ms}ms`,
        });
      } else {
        notifications.show({
          color: "red",
          title: `Test fallo (${result.status})`,
          message: result.error || "sin detalle",
        });
      }
    } catch (e) {
      notifications.show({ color: "red", message: (e as Error).message });
    }
  };

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      title={
        <Group gap={8}>
          <IconPlug size={18} />
          <Text fw={600}>Modulos / Integraciones</Text>
        </Group>
      }
      size="xl"
      centered
    >
      <Group align="flex-start" gap="md" wrap="nowrap">
        <Box style={{ width: 220, minWidth: 220 }}>
          <Group justify="space-between" mb={6}>
            <Text size="xs" c="dimmed">Configurados</Text>
            <Tooltip label="Refrescar" withArrow>
              <ActionIcon size="sm" variant="subtle" onClick={reload}>
                <IconRefresh size={14} />
              </ActionIcon>
            </Tooltip>
          </Group>
          <ScrollArea h={400} type="auto">
            <Stack gap={4}>
              {loading && <Loader size="xs" />}
              {modules.map((m) => (
                <Box
                  key={m.id}
                  p="xs"
                  style={{
                    cursor: "pointer",
                    border: "1px solid var(--mantine-color-gray-3)",
                    borderRadius: 4,
                    background:
                      selectedId === m.id ? "var(--mantine-color-blue-light)" : undefined,
                  }}
                  onClick={() => select(m)}
                >
                  <Group justify="space-between" gap={4} wrap="nowrap">
                    <Text size="sm" fw={600} truncate>
                      {m.name}
                    </Text>
                    <Badge size="xs" color={m.enabled ? "green" : "gray"}>
                      {m.enabled ? "on" : "off"}
                    </Badge>
                  </Group>
                  <Text size="xs" c="dimmed">{m.kind}</Text>
                </Box>
              ))}
              <Button size="xs" variant="light" onClick={startNew} mt="xs">
                + Nuevo
              </Button>
            </Stack>
          </ScrollArea>
        </Box>

        <Divider orientation="vertical" />

        <Box style={{ flex: 1, minWidth: 0 }}>
          {!editing ? (
            <Alert color="gray">Selecciona un modulo o pulsa "Nuevo".</Alert>
          ) : (
            <Tabs value={activeTab} onChange={setActiveTab}>
              <Tabs.List>
                <Tabs.Tab value="form">Configuracion</Tabs.Tab>
                <Tabs.Tab value="logs">Logs</Tabs.Tab>
              </Tabs.List>

              <Tabs.Panel value="form" pt="xs">
                <Stack gap="xs">
                  <Group gap="xs">
                    <TextInput
                      label="Nombre"
                      value={editing.name}
                      onChange={(e) => setEditing({ ...editing, name: e.currentTarget.value })}
                      style={{ flex: 1 }}
                    />
                    <Select
                      label="Kind"
                      value={editing.kind}
                      onChange={(v) => setEditing({ ...editing, kind: v || "jira" })}
                      data={[{ value: "jira", label: "Jira" }]}
                      w={140}
                    />
                  </Group>
                  <Checkbox
                    label="Activo"
                    checked={editing.enabled}
                    onChange={(e) => setEditing({ ...editing, enabled: e.currentTarget.checked })}
                  />
                  <Box>
                    <Text size="xs" fw={600} mb={4}>Eventos</Text>
                    <Group gap="xs">
                      {KANBAN_EVENTS.map((ev) => (
                        <Checkbox
                          key={ev}
                          label={<Code>{ev}</Code>}
                          checked={editing.event_filter.includes(ev)}
                          onChange={(e) => {
                            const next = e.currentTarget.checked
                              ? [...editing.event_filter, ev]
                              : editing.event_filter.filter((x) => x !== ev);
                            setEditing({ ...editing, event_filter: next });
                          }}
                        />
                      ))}
                    </Group>
                  </Box>
                  <JiraConfigEditor editing={editing} setEditing={setEditing} />
                  <Group gap="xs">
                    <Button onClick={save} leftSection={<IconPlugConnected size={14} />}>
                      Guardar
                    </Button>
                    <Button variant="default" onClick={test} leftSection={<IconTestPipe size={14} />}>
                      Probar conexion
                    </Button>
                    {selectedId && (
                      <Button
                        color="red"
                        variant="subtle"
                        onClick={remove}
                        leftSection={<IconTrash size={14} />}
                        ml="auto"
                      >
                        Borrar
                      </Button>
                    )}
                  </Group>
                </Stack>
              </Tabs.Panel>

              <Tabs.Panel value="logs" pt="xs">
                <Group justify="space-between" mb={6}>
                  <Text size="xs" c="dimmed">Ultimas 100 entradas</Text>
                  <ActionIcon
                    size="sm"
                    variant="subtle"
                    onClick={() => selectedId && reloadLogs(selectedId)}
                  >
                    <IconRefresh size={14} />
                  </ActionIcon>
                </Group>
                {logsLoading ? (
                  <Loader size="sm" />
                ) : logs.length === 0 ? (
                  <Text size="sm" c="dimmed">Sin entradas.</Text>
                ) : (
                  <ScrollArea h={400}>
                    <Table withTableBorder striped highlightOnHover stickyHeader>
                      <Table.Thead>
                        <Table.Tr>
                          <Table.Th>Hora</Table.Th>
                          <Table.Th>Evento</Table.Th>
                          <Table.Th>HTTP</Table.Th>
                          <Table.Th>ms</Table.Th>
                          <Table.Th>Error</Table.Th>
                        </Table.Tr>
                      </Table.Thead>
                      <Table.Tbody>
                        {logs.map((l) => (
                          <Table.Tr key={l.id}>
                            <Table.Td>{formatDateTimeShort(l.created_at)}</Table.Td>
                            <Table.Td><Code>{l.event_type}</Code></Table.Td>
                            <Table.Td>
                              <Badge color={l.status >= 400 || l.error ? "red" : "green"} size="sm">
                                {l.status || "-"}
                              </Badge>
                            </Table.Td>
                            <Table.Td>{l.duration_ms}</Table.Td>
                            <Table.Td>
                              <Text size="xs" c="red" lineClamp={2}>{l.error}</Text>
                            </Table.Td>
                          </Table.Tr>
                        ))}
                      </Table.Tbody>
                    </Table>
                  </ScrollArea>
                )}
              </Tabs.Panel>
            </Tabs>
          )}
        </Box>
      </Group>
    </Modal>
  );
}

interface JiraConfigEditorProps {
  editing: KanbanModule;
  setEditing: (m: KanbanModule) => void;
}

function JiraConfigEditor({ editing, setEditing }: JiraConfigEditorProps) {
  const cfg = editing.config as Record<string, unknown>;
  const set = (key: string, value: unknown) =>
    setEditing({ ...editing, config: { ...cfg, [key]: value } });

  const statusMapText = useMemo(() => {
    return JSON.stringify(cfg.status_map ?? {}, null, 2);
  }, [cfg.status_map]);

  if (editing.kind !== "jira") {
    return (
      <Alert color="yellow" mt="xs">
        Editor especifico para esta kind aun no implementado.
      </Alert>
    );
  }

  return (
    <Stack gap="xs">
      <TextInput
        label="Base URL"
        placeholder="https://acme.atlassian.net"
        value={(cfg.base_url as string) || ""}
        onChange={(e) => set("base_url", e.currentTarget.value)}
      />
      <Group gap="xs">
        <TextInput
          label="Email"
          value={(cfg.email as string) || ""}
          onChange={(e) => set("email", e.currentTarget.value)}
          style={{ flex: 1 }}
        />
        <TextInput
          label="API token"
          placeholder={editing.id ? "*** (deja vacio para conservar)" : ""}
          value={(cfg.api_token as string) || ""}
          onChange={(e) => set("api_token", e.currentTarget.value)}
          style={{ flex: 1 }}
        />
      </Group>
      <TextInput
        label="Project key"
        placeholder="KAN"
        value={(cfg.project_key as string) || ""}
        onChange={(e) => set("project_key", e.currentTarget.value)}
      />
      <JsonInput
        label="Status map (columna kanban → transicion Jira)"
        description='{"Doing":"In Progress","Done":"Done"}'
        value={statusMapText}
        autosize
        minRows={3}
        validationError="JSON invalido"
        onChange={(v) => {
          try {
            const parsed = JSON.parse(v);
            set("status_map", parsed);
          } catch {
            // Hold invalid input in textarea via raw state; final save will
            // reuse last valid parse.
          }
        }}
      />
    </Stack>
  );
}
