"use client";

import { useEffect, useRef, useState } from "react";
import { Loader2, Lock, Pencil, Plus, Trash2, X } from "lucide-react";
import SeletorCor, { PALETA_AGENDA } from "./seletor-cor";
import type { CategoriaAgenda } from "./tipos";

/**
 * Categorias da agenda.
 *
 * Sistema e propria na mesma lista, porque e assim que o filtro tambem vai
 * mostrar: a pessoa nao precisa aprender que "Pedidos" e diferente de
 * "Reuniões" por baixo do pano. So a edicao lembra a diferenca — nome e
 * origem de categoria do sistema sao o que get_agenda_range usa para achar a
 * cor de volta, entao ficam travados; a cor continua livre pros dois casos.
 */

function Linha({
  categoria,
  aoSalvar,
  aoApagar,
}: {
  categoria: CategoriaAgenda;
  aoSalvar: (id: string, mudancas: { name?: string; color?: string }) => Promise<string | null>;
  aoApagar: (id: string) => Promise<string | null>;
}) {
  const [editando, setEditando] = useState(false);
  const [nome, setNome] = useState(categoria.name);
  const [cor, setCor] = useState(categoria.color);
  const [salvando, setSalvando] = useState(false);
  const [confirmarApagar, setConfirmarApagar] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  async function salvar() {
    setSalvando(true);
    setErro(null);
    const mudancas: { name?: string; color?: string } = { color: cor };
    if (!categoria.is_system) mudancas.name = nome.trim();
    const falha = await aoSalvar(categoria.id, mudancas);
    setSalvando(false);
    if (falha) setErro(falha);
    else setEditando(false);
  }

  async function apagar() {
    if (!confirmarApagar) {
      setConfirmarApagar(true);
      return;
    }
    setSalvando(true);
    setErro(null);
    const falha = await aoApagar(categoria.id);
    setSalvando(false);
    if (falha) {
      setErro(falha);
      setConfirmarApagar(false);
    }
  }

  return (
    <div className="rounded-2xl border border-[var(--ks-color-border-subtle)] p-3">
      <div className="flex items-center gap-3">
        <span
          aria-hidden
          className="h-8 w-8 shrink-0 rounded-full ring-2 ring-white/60 dark:ring-black/20"
          style={{ background: categoria.color }}
        />
        <div className="min-w-0 flex-1">
          <span className="flex items-center gap-1.5">
            <span className="truncate text-sm font-bold text-[var(--ks-color-text-primary)]">
              {categoria.name}
            </span>
            {categoria.is_system && (
              <span
                title="Categoria do sistema"
                className="flex items-center gap-1 rounded-full bg-[var(--ks-color-bg-soft)] px-1.5 py-0.5 text-[9px] font-black uppercase tracking-wide text-[var(--ks-color-text-muted)]"
              >
                <Lock className="h-2.5 w-2.5" /> Sistema
              </span>
            )}
          </span>
        </div>
        <button
          type="button"
          onClick={() => setEditando((v) => !v)}
          aria-label="Editar categoria"
          className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-color-bg-soft)]"
        >
          <Pencil className="h-4 w-4" />
        </button>
        {!categoria.is_system && (
          <button
            type="button"
            onClick={apagar}
            disabled={salvando}
            aria-label="Apagar categoria"
            className={`flex h-10 min-w-[40px] shrink-0 items-center justify-center rounded-xl px-2 text-xs font-bold transition-colors disabled:opacity-50 ${
              confirmarApagar
                ? "bg-rose-600 text-white hover:bg-rose-700"
                : "text-rose-600 hover:bg-rose-50 dark:hover:bg-rose-500/10"
            }`}
          >
            {confirmarApagar ? "Confirmar" : <Trash2 className="h-4 w-4" />}
          </button>
        )}
      </div>

      {editando && (
        <div className="mt-3 space-y-3 border-t border-[var(--ks-color-border-subtle)] pt-3">
          {!categoria.is_system && (
            <input
              value={nome}
              onChange={(e) => setNome(e.target.value)}
              placeholder="Nome da categoria"
              className="w-full rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] px-3 py-2 text-sm text-[var(--ks-color-text-primary)] focus:border-[var(--ks-color-primary)] focus:outline-none"
            />
          )}
          <SeletorCor valor={cor} aoMudar={setCor} tamanho="sm" />
          {erro && <p className="text-[11px] font-semibold text-rose-600 dark:text-rose-400">{erro}</p>}
          <div className="flex justify-end gap-2">
            <button
              type="button"
              onClick={() => {
                setEditando(false);
                setNome(categoria.name);
                setCor(categoria.color);
                setErro(null);
              }}
              className="rounded-lg px-3 py-2 text-xs font-bold text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-color-bg-soft)]"
            >
              Cancelar
            </button>
            <button
              type="button"
              onClick={salvar}
              disabled={salvando || (!categoria.is_system && !nome.trim())}
              className="flex items-center gap-1.5 rounded-lg bg-[var(--ks-color-primary)] px-3 py-2 text-xs font-black text-white hover:opacity-90 disabled:opacity-50"
            >
              {salvando && <Loader2 className="h-3.5 w-3.5 animate-spin" />}
              Salvar
            </button>
          </div>
        </div>
      )}
      {!editando && erro && <p className="mt-2 text-[11px] font-semibold text-rose-600 dark:text-rose-400">{erro}</p>}
    </div>
  );
}

export default function PainelCategorias({
  aberto,
  categorias,
  aoFechar,
  aoMudou,
}: {
  aberto: boolean;
  categorias: CategoriaAgenda[];
  aoFechar: () => void;
  aoMudou: () => void;
}) {
  const [novoNome, setNovoNome] = useState("");
  const [novaCor, setNovaCor] = useState(PALETA_AGENDA[Math.floor(Math.random() * PALETA_AGENDA.length)]);
  const [criando, setCriando] = useState(false);
  const [erroNovo, setErroNovo] = useState<string | null>(null);
  const primeiroCampo = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (!aberto) return;
    const aoTeclar = (e: KeyboardEvent) => e.key === "Escape" && aoFechar();
    window.addEventListener("keydown", aoTeclar);
    const antes = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const t = setTimeout(() => primeiroCampo.current?.focus(), 80);
    return () => {
      window.removeEventListener("keydown", aoTeclar);
      document.body.style.overflow = antes;
      clearTimeout(t);
    };
  }, [aberto, aoFechar]);

  if (!aberto) return null;

  async function criar() {
    const nome = novoNome.trim();
    if (!nome) return;
    setCriando(true);
    setErroNovo(null);
    try {
      const r = await fetch("/api/agenda/categories", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ name: nome, color: novaCor }),
      });
      const j = (await r.json().catch(() => null)) as { error?: string } | null;
      if (!r.ok) throw new Error(j?.error || "Não foi possível criar a categoria.");
      setNovoNome("");
      setNovaCor(PALETA_AGENDA[Math.floor(Math.random() * PALETA_AGENDA.length)]);
      aoMudou();
    } catch (e) {
      setErroNovo(e instanceof Error ? e.message : "Não foi possível criar a categoria.");
    } finally {
      setCriando(false);
    }
  }

  async function salvarCategoria(id: string, mudancas: { name?: string; color?: string }) {
    try {
      const r = await fetch(`/api/agenda/categories/${id}`, {
        method: "PATCH",
        headers: { "content-type": "application/json" },
        body: JSON.stringify(mudancas),
      });
      const j = (await r.json().catch(() => null)) as { error?: string } | null;
      if (!r.ok) return j?.error || "Não foi possível salvar.";
      aoMudou();
      return null;
    } catch {
      return "Não foi possível salvar.";
    }
  }

  async function apagarCategoria(id: string) {
    try {
      const r = await fetch(`/api/agenda/categories/${id}`, { method: "DELETE" });
      const j = (await r.json().catch(() => null)) as { error?: string } | null;
      if (!r.ok) return j?.error || "Não foi possível apagar.";
      aoMudou();
      return null;
    } catch {
      return "Não foi possível apagar.";
    }
  }

  return (
    <div className="fixed inset-0 z-[70] flex items-end justify-center sm:items-center">
      <button
        type="button"
        aria-label="Fechar"
        onClick={aoFechar}
        className="absolute inset-0 bg-slate-900/40 backdrop-blur-[3px]"
      />
      <div
        role="dialog"
        aria-modal="true"
        aria-label="Categorias da agenda"
        className="relative flex max-h-[88vh] w-full flex-col rounded-t-[28px] bg-[var(--ks-color-bg-body)] shadow-2xl sm:max-w-md sm:rounded-[28px]"
      >
        <div className="mx-auto mt-3 h-1 w-10 shrink-0 rounded-full bg-[var(--ks-color-border-strong)] sm:hidden" />

        <div className="flex items-start justify-between gap-3 px-5 pb-3 pt-4">
          <div>
            <h2 className="text-lg font-black text-[var(--ks-color-text-primary)]">Categorias</h2>
            <p className="text-xs text-[var(--ks-color-text-muted)]">
              A cor daqui vale para tudo que não tem cor própria.
            </p>
          </div>
          <button
            type="button"
            onClick={aoFechar}
            aria-label="Fechar"
            className="flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-color-bg-soft)]"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        <div className="min-h-0 flex-1 space-y-2 overflow-y-auto px-4 pb-4">
          {categorias.map((c) => (
            <Linha key={c.id} categoria={c} aoSalvar={salvarCategoria} aoApagar={apagarCategoria} />
          ))}
        </div>

        <div className="space-y-2.5 border-t border-[var(--ks-color-border-subtle)] p-4">
          <p className="text-[11px] font-black uppercase tracking-wide text-[var(--ks-color-text-muted)]">
            Nova categoria
          </p>
          <div className="flex gap-2">
            <input
              ref={primeiroCampo}
              value={novoNome}
              onChange={(e) => setNovoNome(e.target.value)}
              onKeyDown={(e) => e.key === "Enter" && criar()}
              placeholder="Reuniões, Visita técnica..."
              className="min-w-0 flex-1 rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] px-3 py-2.5 text-sm text-[var(--ks-color-text-primary)] focus:border-[var(--ks-color-primary)] focus:outline-none"
            />
            <button
              type="button"
              onClick={criar}
              disabled={criando || !novoNome.trim()}
              className="flex min-h-[44px] shrink-0 items-center gap-1.5 rounded-xl bg-[var(--ks-color-primary)] px-4 text-sm font-black text-white hover:opacity-90 disabled:opacity-50"
            >
              {criando ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus className="h-4 w-4" />}
              Criar
            </button>
          </div>
          <SeletorCor valor={novaCor} aoMudar={setNovaCor} tamanho="sm" />
          {erroNovo && <p className="text-[11px] font-semibold text-rose-600 dark:text-rose-400">{erroNovo}</p>}
        </div>
      </div>
    </div>
  );
}
