"use client";

/*
 * Um painel: os quadros num grid que se ajusta à tela, com os números já
 * calculados pelo servidor (GET /api/paineis/[id]).
 *
 * No modo de edição cada quadro ganha subir, descer, alterar e remover, e
 * aparece "Adicionar quadro". Cada mudança grava na hora (PATCH) e a resposta
 * já traz o painel recalculado: não existe "salvar tudo" para esquecer.
 */

import { use, useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { ArrowDown, ArrowLeft, ArrowUp, Check, LayoutDashboard, Loader2, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react";

import CaixaDeConfirmacao, { type Confirmacao } from "@/components/ui/caixa-de-confirmacao";
import { Aviso } from "@/components/ui/aviso";
import { Input } from "@/components/ui/input";
import { PageHeader } from "@/components/ui/page-header";
import { chamar, type MetricaDoCatalogo, type ResultadoDoWidget, type Widget } from "@/components/paineis/comum";
import { FormularioDeQuadro } from "@/components/paineis/formulario-de-quadro";
import { ConteudoDoQuadro } from "@/components/paineis/quadro";

type Painel = { id: string; nome: string; descricao: string | null; widgets: Widget[]; atualizado_em: string };
type Resposta = { painel: Painel; dados: Record<string, ResultadoDoWidget>; podeEditar: boolean; metricas?: MetricaDoCatalogo[] };

const ROTULO_DO_PERIODO_CURTO: Record<string, string> = {
  hoje: "Hoje",
  "7d": "7 dias",
  "30d": "30 dias",
  este_mes: "Este mês",
  mes_passado: "Mês passado",
  este_ano: "Este ano",
};

function tamanhoDoQuadro(widget: Widget) {
  if (widget.tipo === "numero") return "col-span-1";
  if (widget.tipo === "tabela" || widget.tipo === "linha") return "col-span-1 md:col-span-2";
  return "col-span-1 md:col-span-2";
}

export default function PainelPage({ params }: { params: Promise<{ id: string }> }) {
  const { id } = use(params);
  const router = useRouter();
  const busca = useSearchParams();

  const [painel, setPainel] = useState<Painel | null>(null);
  const [dados, setDados] = useState<Record<string, ResultadoDoWidget>>({});
  const [metricas, setMetricas] = useState<MetricaDoCatalogo[]>([]);
  const [podeEditar, setPodeEditar] = useState(false);
  const [carregando, setCarregando] = useState(true);
  const [atualizando, setAtualizando] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  const [editando, setEditando] = useState(busca.get("editar") === "1");
  const [nome, setNome] = useState("");
  const [descricao, setDescricao] = useState("");
  const [formulario, setFormulario] = useState<{ aberto: boolean; quadro: Widget | null; chave: number }>({ aberto: false, quadro: null, chave: 0 });
  const [salvando, setSalvando] = useState(false);
  const [erroDoForm, setErroDoForm] = useState<string | null>(null);
  const [confirmacao, setConfirmacao] = useState<Confirmacao | null>(null);
  const [ocupado, setOcupado] = useState(false);

  const aplicar = useCallback((r: Resposta) => {
    setPainel(r.painel);
    setDados(r.dados);
    setPodeEditar(r.podeEditar);
    if (r.metricas) setMetricas(r.metricas);
    setNome(r.painel.nome);
    setDescricao(r.painel.descricao ?? "");
  }, []);

  const carregar = useCallback(
    async (silencioso = false) => {
      if (silencioso) setAtualizando(true);
      else setCarregando(true);
      setErro(null);
      try {
        aplicar(await chamar<Resposta>(`/api/paineis/${id}`));
      } catch (e) {
        setErro(e instanceof Error ? e.message : "Não foi possível abrir o painel.");
      } finally {
        setCarregando(false);
        setAtualizando(false);
      }
    },
    [id, aplicar]
  );

  useEffect(() => {
    void carregar();
  }, [carregar]);

  const gravar = async (mudancas: Partial<{ nome: string; descricao: string; widgets: Array<Partial<Widget>> }>) => {
    const r = await chamar<Resposta>(`/api/paineis/${id}`, { method: "PATCH", body: JSON.stringify(mudancas) });
    aplicar(r);
  };

  const gravarQuadros = async (widgets: Array<Partial<Widget>>) => {
    setAtualizando(true);
    try {
      await gravar({ widgets });
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não foi possível salvar.");
    } finally {
      setAtualizando(false);
    }
  };

  const salvarQuadro = async (quadro: Partial<Widget>) => {
    if (!painel) return;
    setSalvando(true);
    setErroDoForm(null);
    try {
      const lista = quadro.id ? painel.widgets.map((w) => (w.id === quadro.id ? { ...quadro } : w)) : [...painel.widgets, quadro];
      await gravar({ widgets: lista });
      setFormulario((f) => ({ ...f, aberto: false }));
    } catch (e) {
      setErroDoForm(e instanceof Error ? e.message.replace(/^Quadro \d+: /, "") : "Não foi possível salvar.");
    } finally {
      setSalvando(false);
    }
  };

  const mover = (quadroId: string, direcao: -1 | 1) => {
    if (!painel) return;
    const i = painel.widgets.findIndex((w) => w.id === quadroId);
    const j = i + direcao;
    if (i < 0 || j < 0 || j >= painel.widgets.length) return;
    const lista = [...painel.widgets];
    [lista[i], lista[j]] = [lista[j], lista[i]];
    setPainel({ ...painel, widgets: lista });
    void gravarQuadros(lista);
  };

  const remover = (quadro: Widget) =>
    setConfirmacao({
      titulo: `Tirar o quadro "${quadro.titulo}"?`,
      texto: "Só o quadro sai do painel. Os dados da empresa continuam iguais.",
      confirmar: "Tirar quadro",
      tom: "perigo",
      aoConfirmar: async () => {
        if (!painel) return;
        setOcupado(true);
        await gravarQuadros(painel.widgets.filter((w) => w.id !== quadro.id));
        setOcupado(false);
        setConfirmacao(null);
      },
    });

  const concluirEdicao = async () => {
    if (!painel) return;
    if (nome.trim() !== painel.nome || (descricao.trim() || null) !== (painel.descricao || null)) {
      setAtualizando(true);
      try {
        await gravar({ nome: nome.trim(), descricao: descricao.trim() });
      } catch (e) {
        setErro(e instanceof Error ? e.message : "Não foi possível salvar o nome.");
        setAtualizando(false);
        return;
      }
      setAtualizando(false);
    }
    setEditando(false);
    if (busca.get("editar")) router.replace(`/dashboard/paineis/${id}`);
  };

  const excluirPainel = () =>
    setConfirmacao({
      titulo: `Excluir o painel "${painel?.nome ?? ""}"?`,
      texto: "O painel some para toda a equipe. Nenhum pedido, orçamento ou lançamento é apagado.",
      confirmar: "Excluir painel",
      tom: "perigo",
      aoConfirmar: async () => {
        setOcupado(true);
        try {
          await chamar(`/api/paineis/${id}`, { method: "DELETE" });
          router.push("/dashboard/paineis");
        } catch (e) {
          setErro(e instanceof Error ? e.message : "Não foi possível excluir.");
          setOcupado(false);
          setConfirmacao(null);
        }
      },
    });

  if (carregando) {
    return (
      <div className="flex justify-center py-24">
        <Loader2 className="h-8 w-8 animate-spin text-[var(--ks-color-primary)]" />
      </div>
    );
  }

  if (!painel) {
    return (
      <div className="ks-page space-y-4">
        <Aviso tom="ruim" titulo="Painel indisponível" acao={<Link href="/dashboard/paineis" className="ks-button ks-button-secondary">Voltar aos painéis</Link>}>
          {erro ?? "Painel não encontrado."}
        </Aviso>
      </div>
    );
  }

  const acoes = (
    <div className="flex flex-wrap items-center gap-2">
      <Link href="/dashboard/paineis" className="ks-button ks-button-ghost">
        <ArrowLeft className="h-4 w-4" />
        Painéis
      </Link>
      <button type="button" className="ks-button ks-button-secondary" onClick={() => void carregar(true)} disabled={atualizando} title="Recalcular os números">
        <RefreshCw className={`h-4 w-4 ${atualizando ? "animate-spin" : ""}`} />
        Atualizar
      </button>
      {podeEditar ? (
        editando ? (
          <button type="button" className="ks-button ks-button-primary" onClick={() => void concluirEdicao()} disabled={atualizando}>
            <Check className="h-4 w-4" />
            Concluir
          </button>
        ) : (
          <button type="button" className="ks-button ks-button-primary" onClick={() => setEditando(true)}>
            <Pencil className="h-4 w-4" />
            Editar painel
          </button>
        )
      ) : null}
    </div>
  );

  return (
    <div className="ks-page ks-page-wide space-y-6">
      <PageHeader eyebrow="Painel" title={painel.nome} subtitle={painel.descricao ?? undefined} actions={acoes} />

      {erro ? (
        <Aviso tom="ruim" aoFechar={() => setErro(null)}>
          {erro}
        </Aviso>
      ) : null}

      {editando ? (
        <div className="ks-surface flex flex-col gap-3 rounded-xl border border-[var(--ks-color-border-subtle)] p-4 shadow-sm md:flex-row md:items-end">
          <div className="grid flex-1 gap-3 md:grid-cols-2">
            <Input label="Nome do painel" value={nome} maxLength={80} onChange={(e) => setNome(e.target.value)} />
            <Input label="Para que serve" value={descricao} maxLength={400} onChange={(e) => setDescricao(e.target.value)} />
          </div>
          <div className="flex gap-2">
            <button
              type="button"
              className="ks-button ks-button-primary"
              onClick={() => {
                setErroDoForm(null);
                setFormulario((f) => ({ aberto: true, quadro: null, chave: f.chave + 1 }));
              }}
            >
              <Plus className="h-4 w-4" />
              Adicionar quadro
            </button>
            <button type="button" className="ks-button ks-button-ghost text-rose-600" onClick={excluirPainel}>
              <Trash2 className="h-4 w-4" />
              Excluir painel
            </button>
          </div>
        </div>
      ) : null}

      {painel.widgets.length === 0 ? (
        <div className="ks-surface flex flex-col items-center justify-center rounded-xl border border-[var(--ks-color-border-subtle)] px-6 py-16 text-center shadow-sm">
          <span className="mb-4 flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-violet-500 to-purple-600 text-white shadow-[0_10px_24px_rgba(124,58,237,0.32)]">
            <LayoutDashboard className="h-7 w-7" />
          </span>
          <h3 className="text-lg font-semibold text-slate-900">Painel vazio</h3>
          <p className="mb-5 mt-1 max-w-md text-sm text-slate-500">Adicione quadros: faturamento, vendas por vendedor, pedidos atrasados, fluxo de caixa…</p>
          {podeEditar ? (
            <button
              type="button"
              className="ks-button ks-button-primary"
              onClick={() => {
                setEditando(true);
                setErroDoForm(null);
                setFormulario((f) => ({ aberto: true, quadro: null, chave: f.chave + 1 }));
              }}
            >
              <Plus className="h-4 w-4" />
              Adicionar quadro
            </button>
          ) : null}
        </div>
      ) : (
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
          {painel.widgets.map((widget, i) => {
            const resultado = dados[widget.id];
            const periodo = resultado?.periodo ? ROTULO_DO_PERIODO_CURTO[widget.periodo] ?? resultado.periodo.rotulo : resultado?.aviso && !resultado.periodo ? "Agora" : null;
            return (
              <section
                key={widget.id}
                className={`ks-surface flex min-w-0 flex-col rounded-xl border border-[var(--ks-color-border-subtle)] p-4 shadow-sm ${tamanhoDoQuadro(widget)} ${
                  editando ? "ring-1 ring-violet-200" : ""
                }`}
              >
                <header className="mb-3 flex flex-wrap items-start justify-between gap-x-2 gap-y-1">
                  <div className="min-w-[8rem] flex-1">
                    <h2 className="truncate text-sm font-semibold text-slate-700">{widget.titulo}</h2>
                    {periodo ? <p className="text-xs text-slate-400">{periodo}</p> : null}
                  </div>
                  {editando ? (
                    <div className="-mr-1.5 flex shrink-0 items-center gap-0.5">
                      <button type="button" title="Mover para trás" className="ks-button ks-button-ghost ks-button-icon ks-button-sm" disabled={i === 0} onClick={() => mover(widget.id, -1)}>
                        <ArrowUp className="h-4 w-4" />
                      </button>
                      <button
                        type="button"
                        title="Mover para a frente"
                        className="ks-button ks-button-ghost ks-button-icon ks-button-sm"
                        disabled={i === painel.widgets.length - 1}
                        onClick={() => mover(widget.id, 1)}
                      >
                        <ArrowDown className="h-4 w-4" />
                      </button>
                      <button
                        type="button"
                        title="Alterar quadro"
                        className="ks-button ks-button-ghost ks-button-icon ks-button-sm"
                        onClick={() => {
                          setErroDoForm(null);
                          setFormulario((f) => ({ aberto: true, quadro: widget, chave: f.chave + 1 }));
                        }}
                      >
                        <Pencil className="h-4 w-4" />
                      </button>
                      <button type="button" title="Tirar quadro" className="ks-button ks-button-ghost ks-button-icon ks-button-sm text-rose-600" onClick={() => remover(widget)}>
                        <Trash2 className="h-4 w-4" />
                      </button>
                    </div>
                  ) : null}
                </header>
                <div className={`flex-1 ${atualizando ? "opacity-60 transition-opacity" : ""}`}>
                  <ConteudoDoQuadro widget={widget} resultado={resultado} />
                </div>
                {resultado?.aviso && resultado.periodo ? <p className="mt-3 text-xs text-slate-500">{resultado.aviso}</p> : null}
              </section>
            );
          })}
        </div>
      )}

      {formulario.aberto ? (
        <FormularioDeQuadro
          key={formulario.chave}
          aberto
          metricas={metricas}
          inicial={formulario.quadro}
          salvando={salvando}
          erro={erroDoForm}
          aoSalvar={(quadro) => void salvarQuadro(quadro)}
          aoFechar={() => (!salvando ? setFormulario((f) => ({ ...f, aberto: false })) : undefined)}
        />
      ) : null}

      <CaixaDeConfirmacao pedido={confirmacao} ocupado={ocupado} aoFechar={() => (!ocupado ? setConfirmacao(null) : undefined)} />
    </div>
  );
}
