import { Badge, Divider, Group, Loader, Stack, Table, Text, Timeline } from "@mantine/core";
import {
  IconArrowsHorizontal,
  IconCalendarDue,
  IconCalendarOff,
  IconCheck,
  IconColumns3,
  IconEdit,
  IconLock,
  IconLockOpen,
  IconPalette,
  IconPlus,
  IconTag,
  IconUser,
  IconUserMinus,
  IconUserPlus,
} from "@tabler/icons-react";
import { useEffect, useMemo, useState } from "react";
import { cardHistory, listUsers } from "../api";
import type { Card, CardEvent, CardHistoryResponse, Column, User } from "../types";
import { formatDuration } from "./format";

interface Props {
  card: Card;
  columns?: Column[];
}

interface UnifiedEvent {
  id: string;
  ts: string;
  kind: string;
  actorID: string | null;
  detail: string;
  icon: React.ReactNode;
  color: string;
  doneColumn?: boolean;
}

function parsePayload(p: string): Record<string, unknown> {
  try { return JSON.parse(p); } catch { return {}; }
}

function eventToUnified(e: CardEvent): UnifiedEvent {
  const p = parsePayload(e.payload);
  switch (e.kind) {
    case "created":
      return { id: e.id, ts: e.created_at, kind: "Creada", actorID: e.actor_id, detail: String(p.title || ""), icon: <IconPlus size={12} />, color: "green" };
    case "title_changed":
      return { id: e.id, ts: e.created_at, kind: "Titulo", actorID: e.actor_id, detail: `"${p.old}" → "${p.new}"`, icon: <IconEdit size={12} />, color: "blue" };
    case "requester_changed":
      return { id: e.id, ts: e.created_at, kind: "Solicitante", actorID: e.actor_id, detail: `"${p.old || "(vacio)"}" → "${p.new || "(vacio)"}"`, icon: <IconEdit size={12} />, color: "orange" };
    case "description_changed":
      return { id: e.id, ts: e.created_at, kind: "Descripcion", actorID: e.actor_id, detail: "edicion", icon: <IconEdit size={12} />, color: "blue" };
    case "color_changed":
      return { id: e.id, ts: e.created_at, kind: "Color", actorID: e.actor_id, detail: String(p.color || ""), icon: <IconPalette size={12} />, color: "violet" };
    case "tags_changed":
      return { id: e.id, ts: e.created_at, kind: "Tags", actorID: e.actor_id, detail: Array.isArray(p.tags) ? (p.tags as string[]).join(", ") || "(sin tags)" : "", icon: <IconTag size={12} />, color: "grape" };
    case "assigned":
      return { id: e.id, ts: e.created_at, kind: "Asignada", actorID: e.actor_id, detail: String(p.assignee_id || ""), icon: <IconUserPlus size={12} />, color: "teal" };
    case "unassigned":
      return { id: e.id, ts: e.created_at, kind: "Sin asignar", actorID: e.actor_id, detail: "", icon: <IconUserMinus size={12} />, color: "gray" };
    case "deadline_set": {
      const d = String(p.deadline || "");
      return { id: e.id, ts: e.created_at, kind: "Deadline", actorID: e.actor_id, detail: d ? d.slice(0, 10) : "", icon: <IconCalendarDue size={12} />, color: "orange" };
    }
    case "deadline_cleared":
      return { id: e.id, ts: e.created_at, kind: "Deadline quitado", actorID: e.actor_id, detail: p.prev ? String(p.prev).slice(0, 10) : "", icon: <IconCalendarOff size={12} />, color: "gray" };
    default:
      return { id: e.id, ts: e.created_at, kind: e.kind, actorID: e.actor_id, detail: e.payload, icon: <IconEdit size={12} />, color: "gray" };
  }
}

export function HistoryModal({ card, columns = [] }: Props) {
  const [data, setData] = useState<CardHistoryResponse | null>(null);
  const [users, setUsers] = useState<User[]>([]);

  const columnById = useMemo(() => {
    const m = new Map<string, Column>();
    for (const c of columns) m.set(c.id, c);
    return m;
  }, [columns]);

  const isDoneColumn = (columnId: string) => columnById.get(columnId)?.is_done === true;

  useEffect(() => {
    cardHistory(card.id)
      .then(setData)
      .catch(() =>
        setData({ column_history: [], lock_periods: [], events: [], total_locked_ms: 0, currently_locked: false })
      );
    listUsers().then(setUsers).catch(() => {});
  }, [card.id]);

  const userById = useMemo(() => {
    const m = new Map<string, User>();
    for (const u of users) m.set(u.id, u);
    return m;
  }, [users]);

  const unified = useMemo(() => {
    if (!data) return [] as UnifiedEvent[];
    const out: UnifiedEvent[] = [];
    for (const e of data.events || []) out.push(eventToUnified(e));
    for (const h of data.column_history || []) {
      const done = isDoneColumn(h.column_id);
      out.push({
        id: "h_in_" + h.id,
        ts: h.entered_at,
        kind: done ? "Hecho en columna" : "Mueve a columna",
        actorID: h.actor_id,
        detail: h.column_name || h.column_id,
        icon: done ? <IconCheck size={12} /> : <IconArrowsHorizontal size={12} />,
        color: done ? "green" : "blue",
        doneColumn: done,
      });
    }
    for (const p of data.lock_periods || []) {
      out.push({ id: "lk_" + p.id, ts: p.locked_at, kind: "Bloqueada", actorID: p.actor_id, detail: "", icon: <IconLock size={12} />, color: "yellow" });
      if (p.unlocked_at) {
        out.push({ id: "lku_" + p.id, ts: p.unlocked_at, kind: "Desbloqueada", actorID: p.actor_id, detail: formatDuration(p.duration_ms), icon: <IconLockOpen size={12} />, color: "yellow" });
      }
    }
    return out.sort((a, b) => a.ts.localeCompare(b.ts));
  }, [data, columnById]);

  if (!data) {
    return (
      <Group justify="center" p="xl">
        <Loader size="sm" />
      </Group>
    );
  }

  const { column_history, total_locked_ms, currently_locked } = data;

  if (unified.length === 0) {
    return <Text c="dimmed">Sin historial.</Text>;
  }

  // Per-column time stats: sum duration_ms by column_id from column_history.
  // Currently-active entry (exited_at=null) gets duration_ms = now - entered_at.
  const nowMs = Date.now();
  const perColumnMs = new Map<string, { name: string; isDone: boolean; ms: number; visits: number }>();
  for (const h of column_history) {
    const dur = h.exited_at ? h.duration_ms : Math.max(0, nowMs - new Date(h.entered_at).getTime());
    const key = h.column_id;
    const prev = perColumnMs.get(key);
    const meta = columnById.get(key);
    perColumnMs.set(key, {
      name: h.column_name || meta?.name || key,
      isDone: meta?.is_done ?? false,
      ms: (prev?.ms ?? 0) + dur,
      visits: (prev?.visits ?? 0) + 1,
    });
  }
  const perColumnRows = Array.from(perColumnMs.entries())
    .map(([id, v]) => ({ id, ...v }))
    .sort((a, b) => b.ms - a.ms);

  const userLabel = (id: string | null): string => {
    if (!id) return "";
    const u = userById.get(id);
    if (!u) return id;
    return u.display_name || u.username;
  };

  return (
    <Stack gap="md">
      <Text size="sm" c="dimmed">Linea de tiempo completa de la tarjeta.</Text>
      <Timeline active={unified.length} bulletSize={22} lineWidth={2}>
        {unified.map((e) => (
          <Timeline.Item
            key={e.id}
            bullet={e.icon}
            color={e.color}
            lineVariant={e.doneColumn ? "solid" : undefined}
            title={
              <Group gap={6} wrap="wrap">
                <Text fw={500} size="sm">{e.kind}</Text>
                {e.actorID && (
                  <Badge size="xs" variant="light" color="cyan" leftSection={<IconUser size={10} />}>
                    {userLabel(e.actorID)}
                  </Badge>
                )}
                {e.detail && (
                  <Badge size="xs" variant="outline" color={e.color}>
                    {e.detail}
                  </Badge>
                )}
              </Group>
            }
          >
            <Text size="xs" c="dimmed">{new Date(e.ts).toLocaleString()}</Text>
          </Timeline.Item>
        ))}
      </Timeline>

      <Divider />

      <Stack gap={6}>
        <Group gap={6} align="center" wrap="wrap">
          <IconColumns3 size={14} />
          <Text fw={500} size="sm">Tiempo por columna</Text>
          <Badge size="xs" variant="light" color="gray">{column_history.length} entradas</Badge>
          <Text size="xs" c="dimmed" ml="auto">
            <IconLock size={11} style={{ verticalAlign: "middle" }} />{" "}
            <Text span size="xs" fw={500} c={total_locked_ms > 0 ? "yellow" : "dimmed"}>
              {formatDuration(total_locked_ms)}
            </Text>{" "}
            bloqueada{currently_locked ? " (en curso)" : ""}
          </Text>
        </Group>
        {perColumnRows.length > 0 ? (
          <Table withTableBorder withColumnBorders striped="even" verticalSpacing={4} fz="xs">
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Columna</Table.Th>
                <Table.Th style={{ width: 60 }}>Visitas</Table.Th>
                <Table.Th style={{ width: 130 }}>Tiempo total</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {perColumnRows.map((r) => (
                <Table.Tr key={r.id}>
                  <Table.Td>
                    <Group gap={4} wrap="nowrap">
                      {r.isDone && <IconCheck size={12} color="var(--mantine-color-green-6)" />}
                      <Text size="xs" fw={r.isDone ? 600 : 400}>{r.name}</Text>
                    </Group>
                  </Table.Td>
                  <Table.Td>{r.visits}</Table.Td>
                  <Table.Td>{formatDuration(r.ms)}</Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        ) : (
          <Text size="xs" c="dimmed">Sin movimientos entre columnas.</Text>
        )}
      </Stack>
    </Stack>
  );
}
