"use client";

import { useEffect, useRef, useState, type PointerEvent as EventoDePonteiro, type RefObject } from "react";
import { ChevronLeft, ChevronRight, Copy, CopyPlus, FilePlus2, LayoutGrid, MoreHorizontal, Plus, Trash2, X } from "lucide-react";
import { LIMITE_DE_PAGINAS, numeracaoDosPosts, type DocumentoDoBanner } from "@/lib/banner-editor/documento";
import { Miniatura } from "./paineis";

/*
  As páginas do projeto (carrossel, apresentação, várias artes do mesmo
  tamanho), no jeito do Canva: uma tira de miniaturas embaixo da arte. Clicar
  numa página abre ela no palco; o "..." de cada uma duplica, muda de lugar ou
  apaga; o "+" do fim pergunta se a página nova vem em branco (só a página,
  no mesmo tamanho) ou duplicada com todo o design da página aberta.
*/

export type AcaoNaPagina = "duplicar" | "esquerda" | "direita" | "apagar";

/**
 * Arrastar para mudar a ordem (na tira e na grade): cada item tem
 * data-ordem={i} dentro da caixa. Até andar 6 px é um clique (abre a
 * página); depois vira arrasto e a marca mostra onde a página entra. O alvo
 * é a posição de inserção na lista de antes (0..n).
 */
function useReordenar(caixa: RefObject<HTMLDivElement | null>, aoMover: (de: number, para: number) => void, aoClicar: (i: number) => void) {
  const [arrasto, setArrasto] = useState<{ de: number; alvo: number; x: number; y: number } | null>(null);
  const comecar = (i: number, e: EventoDePonteiro) => {
    if (e.button !== 0) return;
    const x0 = e.clientX;
    const y0 = e.clientY;
    const caixas = [...(caixa.current?.querySelectorAll<HTMLElement>("[data-ordem]") || [])].map((el) => el.getBoundingClientRect());
    let andou = false;
    let alvo = i;
    const mover = (ev: PointerEvent) => {
      if (!andou && Math.hypot(ev.clientX - x0, ev.clientY - y0) < 6) return;
      andou = true;
      /* A página mais perto do ponteiro; antes ou depois dela pelo meio. */
      let perto = 0;
      let menor = Infinity;
      caixas.forEach((r, j) => {
        const d = Math.hypot(ev.clientX - (r.left + r.width / 2), (ev.clientY - (r.top + r.height / 2)) * 1.6);
        if (d < menor) {
          menor = d;
          perto = j;
        }
      });
      const r = caixas[perto];
      alvo = r ? (ev.clientX > r.left + r.width / 2 ? perto + 1 : perto) : i;
      setArrasto({ de: i, alvo, x: ev.clientX, y: ev.clientY });
    };
    const soltar = () => {
      window.removeEventListener("pointermove", mover);
      window.removeEventListener("pointerup", soltar);
      window.removeEventListener("pointercancel", soltar);
      setArrasto(null);
      if (!andou) aoClicar(i);
      else if (alvo !== i && alvo !== i + 1) aoMover(i, alvo > i ? alvo - 1 : alvo);
    };
    window.addEventListener("pointermove", mover);
    window.addEventListener("pointerup", soltar);
    window.addEventListener("pointercancel", soltar);
  };
  return { arrasto, comecar };
}

/** Fecha o que estiver aberto ao clicar fora. */
function useFecharFora(aberto: boolean, fechar: () => void) {
  const caixa = useRef<HTMLDivElement | null>(null);
  useEffect(() => {
    if (!aberto) return;
    const fora = (e: MouseEvent) => {
      if (!caixa.current?.contains(e.target as Node)) fechar();
    };
    document.addEventListener("mousedown", fora);
    return () => document.removeEventListener("mousedown", fora);
  }, [aberto, fechar]);
  return caixa;
}

const ALTURA = 58;

/*
 * A tira acompanha a arte com um respiro: enquanto a pessoa arrasta ou digita,
 * a miniatura da página aberta espera ela parar (refazer a miniatura a cada
 * passo travava as artes pesadas). Página nova, apagada ou trocada aparece na hora.
 */
export function usePaginasDaTira(paginas: DocumentoDoBanner[], atual: number) {
  const [atrasadas, setAtrasadas] = useState(paginas);
  useEffect(() => {
    const t = window.setTimeout(() => setAtrasadas(paginas), 400);
    return () => window.clearTimeout(t);
  }, [paginas]);
  const soAAberta = atrasadas.length === paginas.length && paginas.every((p, i) => i === atual || p === atrasadas[i]);
  return soAAberta ? atrasadas : paginas;
}

export function TiraDePaginas({
  paginas,
  atual,
  aoIr,
  aoAdicionar,
  aoAgir,
  aoMover,
  aoVerTodas,
}: {
  paginas: DocumentoDoBanner[];
  atual: number;
  aoIr: (i: number) => void;
  aoAdicionar: (jeito: "branca" | "duplicar") => void;
  aoAgir: (i: number, acao: AcaoNaPagina) => void;
  aoMover: (de: number, para: number) => void;
  aoVerTodas: () => void;
}) {
  const [maisAberto, setMaisAberto] = useState(false);
  const [menuDe, setMenuDe] = useState<number | null>(null);
  const caixaDoMais = useFecharFora(maisAberto, () => setMaisAberto(false));
  const caixaDoMenu = useFecharFora(menuDe !== null, () => setMenuDe(null));
  const cheia = paginas.length >= LIMITE_DE_PAGINAS;
  /* Cada miniatura no formato da sua página (o projeto pode ter post e story juntos). */
  const larguraDe = (p: DocumentoDoBanner | undefined) => (p ? Math.max(30, Math.min(104, (ALTURA * p.largura) / p.altura)) : 46);
  const largura = larguraDe(paginas[atual]);
  const tira = useRef<HTMLDivElement | null>(null);
  const { arrasto, comecar } = useReordenar(tira, aoMover, aoIr);
  const numeros = numeracaoDosPosts(paginas);

  /* A página aberta sempre à vista na tira. */
  useEffect(() => {
    tira.current?.querySelector<HTMLElement>(`[data-pagina="${atual}"]`)?.scrollIntoView({ block: "nearest", inline: "nearest" });
  }, [atual, paginas.length]);

  const item = "flex w-full items-center gap-2.5 rounded-[8px] px-2.5 py-2 text-left text-[12.5px] font-medium text-[#2B2640] transition hover:bg-[#F3F1F9] disabled:opacity-35 disabled:hover:bg-transparent";

  return (
    <div className="pointer-events-auto relative flex max-w-full items-end gap-2 rounded-[14px] bg-white px-2.5 pb-2 pt-2.5 shadow-[0_2px_6px_rgba(20,11,43,0.06),0_10px_30px_rgba(20,11,43,0.10)] ring-1 ring-black/5">
      <div
        ref={tira}
        className="flex min-w-0 items-end gap-2 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
        onWheel={(e) => {
          /* A roda na tira anda pelas páginas (não dá zoom). */
          e.stopPropagation();
          if (tira.current) tira.current.scrollLeft += e.deltaY + e.deltaX;
        }}
      >
        {paginas.map((pagina, i) => (
          <div key={i} data-pagina={i} data-ordem={i} className={`group relative shrink-0 ${arrasto?.de === i ? "opacity-40" : ""}`}>
            {arrasto && arrasto.alvo === i ? <MarcaDeInsercao /> : null}
            {arrasto && i === paginas.length - 1 && arrasto.alvo === paginas.length ? <MarcaDeInsercao fim /> : null}
            <button
              type="button"
              /* O mouse abre ou arrasta (useReordenar); o teclado abre pelo clique. */
              onPointerDown={(e) => comecar(i, e)}
              onClick={(e) => e.detail === 0 && aoIr(i)}
              title={`Página ${i + 1} (arraste para mudar a ordem)`}
              className={`block touch-none overflow-hidden rounded-[8px] transition ${i === atual ? "ring-2 ring-[#7C3AED] ring-offset-2" : "ring-1 ring-black/10 hover:ring-[#C4B5FD]"}`}
              style={{ width: larguraDe(pagina), height: ALTURA }}
            >
              <span className="pointer-events-none block" style={{ width: larguraDe(pagina), height: ALTURA }}>
                <Miniatura doc={pagina} largura={larguraDe(pagina)} contagem={numeros[i]} />
              </span>
            </button>
            <span className={`mt-1 block text-center text-[10.5px] font-bold tabular-nums ${i === atual ? "text-[#6D28D9]" : "text-[#8A849E]"}`}>{i + 1}</span>
            <button
              type="button"
              title="Opções da página"
              /* Sem isto, o "clicar fora" fecharia o menu antes do clique reabrir. */
              onMouseDown={(e) => e.stopPropagation()}
              onClick={() => setMenuDe((m) => (m === i ? null : i))}
              className={`absolute right-1 top-1 flex h-6 w-6 items-center justify-center rounded-[6px] bg-white/95 text-[#4B4760] shadow-sm ring-1 ring-black/10 transition hover:text-[#1F1B2E] ${menuDe === i ? "opacity-100" : "opacity-0 group-hover:opacity-100"}`}
            >
              <MoreHorizontal size={14} />
            </button>
          </div>
        ))}
      </div>

      <div ref={caixaDoMais} className="relative flex shrink-0 items-center pb-[19px]">
        <button
          type="button"
          title={cheia ? `No máximo ${LIMITE_DE_PAGINAS} páginas` : "Adicionar página"}
          disabled={cheia}
          onClick={() => setMaisAberto((v) => !v)}
          className={`flex items-center justify-center rounded-[8px] border-2 border-dashed transition disabled:opacity-40 ${maisAberto ? "border-[#7C3AED] bg-[#F1ECFF] text-[#6D28D9]" : "border-[#D6D1E6] text-[#6B6584] hover:border-[#A78BFA] hover:text-[#6D28D9]"}`}
          style={{ width: Math.max(46, largura * 0.7), height: ALTURA }}
        >
          <Plus size={20} />
        </button>
        {paginas.length > 1 ? (
          <button type="button" onClick={aoVerTodas} title="Ver todas as páginas" aria-label="Ver todas as páginas" className="ml-1.5 inline-flex h-8 w-8 items-center justify-center rounded-[8px] text-[#6B6584] transition hover:bg-[#F3F1F9] hover:text-[#6D28D9]">
            <LayoutGrid size={17} />
          </button>
        ) : null}
        {maisAberto ? (
          <div className="absolute bottom-[calc(100%+10px)] right-0 z-50 w-[250px] rounded-[14px] bg-white p-1.5 shadow-[0_18px_50px_rgba(20,11,43,0.25)] ring-1 ring-black/5">
            <p className="px-2.5 pb-1 pt-1.5 text-[11px] font-bold uppercase tracking-[0.1em] text-[#8A849E]">Nova página</p>
            <button
              type="button"
              className={item}
              onClick={() => {
                setMaisAberto(false);
                aoAdicionar("branca");
              }}
            >
              <FilePlus2 size={17} className="shrink-0 text-[#7C3AED]" />
              <span>
                <span className="block font-semibold">Página em branco</span>
                <span className="block text-[11.5px] font-normal text-[#8A849E]">Só a página, no mesmo tamanho</span>
              </span>
            </button>
            <button
              type="button"
              className={item}
              onClick={() => {
                setMaisAberto(false);
                aoAdicionar("duplicar");
              }}
            >
              <CopyPlus size={17} className="shrink-0 text-[#7C3AED]" />
              <span>
                <span className="block font-semibold">Duplicar com o design</span>
                <span className="block text-[11.5px] font-normal text-[#8A849E]">Copia tudo da página {atual + 1}</span>
              </span>
            </button>
          </div>
        ) : null}
      </div>

      {menuDe !== null ? (
        <div ref={caixaDoMenu} className="absolute bottom-[calc(100%+10px)] left-1/2 z-50 w-[220px] -translate-x-1/2 rounded-[14px] bg-white p-1.5 shadow-[0_18px_50px_rgba(20,11,43,0.25)] ring-1 ring-black/5">
          <p className="px-2.5 pb-1 pt-1.5 text-[11px] font-bold uppercase tracking-[0.1em] text-[#8A849E]">Página {menuDe + 1}</p>
          {(
            [
              ["duplicar", "Duplicar página", Copy, cheia],
              ["esquerda", "Mover para a esquerda", ChevronLeft, menuDe === 0],
              ["direita", "Mover para a direita", ChevronRight, menuDe === paginas.length - 1],
              ["apagar", "Apagar página", Trash2, paginas.length < 2],
            ] as Array<[AcaoNaPagina, string, typeof Copy, boolean]>
          ).map(([acao, rotulo, Icone, desligado]) => (
            <button
              key={acao}
              type="button"
              disabled={desligado}
              className={`${item} ${acao === "apagar" ? "hover:!bg-[#FFE4E6] hover:!text-[#BE123C]" : ""}`}
              onClick={() => {
                const i = menuDe;
                setMenuDe(null);
                aoAgir(i, acao);
              }}
            >
              <Icone size={16} className="shrink-0" />
              {rotulo}
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}

/** Onde a página arrastada entra (antes do item, ou depois do último). */
function MarcaDeInsercao({ fim = false }: { fim?: boolean }) {
  return <span className={`pointer-events-none absolute top-0 z-10 h-full w-[3px] rounded-full bg-[#7C3AED] ${fim ? "-right-[6px]" : "-left-[6px]"}`} />;
}

const ALTURA_NA_GRADE = 170;

/**
 * Todas as páginas de uma vez, grandes, sobre o palco: arrastar muda a
 * ordem, clicar abre a página (e fecha a grade), e cada uma duplica ou
 * apaga pelo botão que aparece ao passar o mouse.
 */
export function GradeDePaginas({
  paginas,
  atual,
  aoIr,
  aoAgir,
  aoMover,
  aoAdicionar,
  aoFechar,
}: {
  paginas: DocumentoDoBanner[];
  atual: number;
  aoIr: (i: number) => void;
  aoAgir: (i: number, acao: AcaoNaPagina) => void;
  aoMover: (de: number, para: number) => void;
  aoAdicionar: (jeito: "branca" | "duplicar") => void;
  aoFechar: () => void;
}) {
  const grade = useRef<HTMLDivElement | null>(null);
  const { arrasto, comecar } = useReordenar(grade, aoMover, (i) => {
    aoIr(i);
    aoFechar();
  });
  const cheia = paginas.length >= LIMITE_DE_PAGINAS;
  const numeros = numeracaoDosPosts(paginas);
  const larguraDe = (p: DocumentoDoBanner) => Math.max(70, Math.min(320, (ALTURA_NA_GRADE * p.largura) / p.altura));
  const arrastada = arrasto ? paginas[arrasto.de] : null;

  useEffect(() => {
    const tecla = (e: KeyboardEvent) => {
      if (e.key !== "Escape") return;
      e.stopPropagation();
      aoFechar();
    };
    window.addEventListener("keydown", tecla, true);
    return () => window.removeEventListener("keydown", tecla, true);
  }, [aoFechar]);

  const botao = "flex h-7 w-7 items-center justify-center rounded-[7px] bg-white/95 text-[#4B4760] shadow-sm ring-1 ring-black/10 transition hover:text-[#1F1B2E] disabled:opacity-40";

  return (
    <div className="absolute inset-0 z-[45] overflow-y-auto bg-[#EEEDF3]" data-grade-de-paginas>
      <div className="sticky top-0 z-10 flex items-center gap-3 bg-[#EEEDF3]/95 px-8 py-4 backdrop-blur">
        <p className="text-[15px] font-bold text-[#1F1B2E]">Todas as páginas</p>
        <span className="rounded-full bg-white px-2 py-0.5 text-[11.5px] font-bold tabular-nums text-[#6B6584] ring-1 ring-black/5">{paginas.length}</span>
        <p className="text-[12.5px] text-[#8A849E]">Arraste para mudar a ordem. Clique para abrir.</p>
        <div className="ml-auto flex items-center gap-2">
          <button type="button" disabled={cheia} onClick={() => aoAdicionar("branca")} className="flex h-9 items-center gap-1.5 rounded-[10px] bg-white px-3 text-[12.5px] font-semibold text-[#4B4760] ring-1 ring-black/5 transition hover:text-[#6D28D9] disabled:opacity-40">
            <Plus size={15} /> Página em branco
          </button>
          <button type="button" onClick={aoFechar} className="flex h-9 items-center gap-1.5 rounded-[10px] bg-[#7C3AED] px-3.5 text-[12.5px] font-bold text-white transition hover:bg-[#6D28D9]">
            <X size={15} /> Fechar
          </button>
        </div>
      </div>
      <div ref={grade} className="flex flex-wrap items-end gap-x-9 gap-y-8 px-8 pb-10 pt-2">
        {paginas.map((pagina, i) => (
          <div key={i} data-ordem={i} className={`group relative shrink-0 ${arrasto?.de === i ? "opacity-35" : ""}`}>
            {arrasto && arrasto.alvo === i ? <span className="pointer-events-none absolute -left-[20px] top-0 h-[170px] w-1 rounded-full bg-[#7C3AED]" /> : null}
            {arrasto && i === paginas.length - 1 && arrasto.alvo === paginas.length ? <span className="pointer-events-none absolute -right-[20px] top-0 h-[170px] w-1 rounded-full bg-[#7C3AED]" /> : null}
            <button
              type="button"
              onPointerDown={(e) => comecar(i, e)}
              onClick={(e) => {
                if (e.detail !== 0) return;
                aoIr(i);
                aoFechar();
              }}
              title={`Página ${i + 1}`}
              className={`block touch-none cursor-grab overflow-hidden rounded-[10px] bg-white shadow-[0_2px_10px_rgba(20,11,43,0.08)] transition active:cursor-grabbing ${i === atual ? "ring-[3px] ring-[#7C3AED] ring-offset-2 ring-offset-[#EEEDF3]" : "ring-1 ring-black/10 hover:ring-2 hover:ring-[#C4B5FD]"}`}
              style={{ width: larguraDe(pagina), height: ALTURA_NA_GRADE }}
            >
              <span className="pointer-events-none flex h-full w-full items-center justify-center">
                <Miniatura doc={pagina} largura={Math.min(larguraDe(pagina), (ALTURA_NA_GRADE * pagina.largura) / pagina.altura)} contagem={numeros[i]} />
              </span>
            </button>
            <div className="mt-2 flex items-center justify-between gap-2">
              <span className={`text-[12px] font-bold tabular-nums ${i === atual ? "text-[#6D28D9]" : "text-[#6B6584]"}`}>Página {i + 1}</span>
              <span className="text-[10.5px] tabular-nums text-[#A39DB8]">
                {pagina.largura} × {pagina.altura}
              </span>
            </div>
            <div className="absolute right-2 top-2 flex gap-1 opacity-0 transition group-hover:opacity-100">
              <button type="button" title="Duplicar página" aria-label={`Duplicar a página ${i + 1}`} disabled={cheia} onPointerDown={(e) => e.stopPropagation()} onClick={() => aoAgir(i, "duplicar")} className={botao}>
                <Copy size={14} />
              </button>
              <button type="button" title="Apagar página" aria-label={`Apagar a página ${i + 1}`} disabled={paginas.length < 2} onPointerDown={(e) => e.stopPropagation()} onClick={() => aoAgir(i, "apagar")} className={`${botao} hover:!text-[#BE123C]`}>
                <Trash2 size={14} />
              </button>
            </div>
          </div>
        ))}
      </div>
      {arrasto && arrastada ? (
        <div className="pointer-events-none fixed z-[100] -translate-x-1/2 -translate-y-1/2 rotate-[-3deg] overflow-hidden rounded-[10px] opacity-90 shadow-[0_18px_40px_rgba(20,11,43,0.3)] ring-2 ring-[#7C3AED]" style={{ left: arrasto.x, top: arrasto.y }}>
          <Miniatura doc={arrastada} largura={larguraDe(arrastada) * 0.6} />
        </div>
      ) : null}
    </div>
  );
}
