"use client";

import { useEffect, useRef, useState } from "react";
import { Check, LayoutGrid, Store, Building2, Shirt, ArrowUpRight, ImageOff } from "lucide-react";

type TemaDoCartao = "default" | "vitrine" | "vendor" | "boutique";

type CatalogThemeOption = {
  value: TemaDoCartao;
  label: string;
  description: string;
};

const THEME_OPTIONS: CatalogThemeOption[] = [
  {
    value: "default",
    label: "Padrão",
    description: "Layout limpo com foco em listagem direta.",
  },
  {
    value: "vitrine",
    label: "Vitrine",
    description: "Layout estilo e-commerce com destaque para banners e categorias.",
  },
  {
    value: "vendor",
    label: "Vendor",
    description: "Loja de gráfica: menu de categorias fixo, grade de quatro colunas e página de produto com galeria fixa.",
  },
  {
    value: "boutique",
    label: "Ateliê",
    description: "Cabeçalho sobre o banner, tipografia de revista, stories em destaque e vitrine de vídeos para comprar pelo vídeo.",
  },
];

const THEME_ICONS = {
  default: LayoutGrid,
  vitrine: Store,
  vendor: Building2,
  boutique: Shirt,
} as const;

/*
  A prévia de cada cartão é a PRÓPRIA loja naquele tema, num quadro: a home
  desenhada em 1440x900 (uma tela de computador) e reduzida para a largura do
  cartão. O painel pede uma passagem de prévia (api/loja/previa-do-tema) e a
  loja só aceita o ?tema= com ela; a visita não conta nos relatórios e nada é
  gravado. Escolher o tema continua sendo o "Salvar alterações" da tela.
*/
const LARGURA_DA_TELA = 1440;
const ALTURA_DA_TELA = 900;
/* No modo de desenvolvimento a loja compila cada tema na primeira visita. */
const ESPERA_DO_QUADRO_MS = 45_000;
/* A passagem vale 2 h: renova antes, para o "Ver em tela cheia" nunca abrir vencido. */
const RENOVAR_A_CADA_MS = 90 * 60 * 1000;

type Previa = { endereco: string } | { indisponivel: "sem-loja" | "falhou" };

function usePreviaDaLoja(): Previa | null {
  const [previa, setPrevia] = useState<Previa | null>(null);
  useEffect(() => {
    let vivo = true;
    const pedir = async () => {
      try {
        const resposta = await fetch("/api/loja/previa-do-tema", {
          method: "POST",
          headers: { "content-type": "application/json" },
          /* Como no editor da página inicial: fora de produção, ?loja= na tela
             aponta a loja local (a de desenvolvimento roda na 3005). */
          body: JSON.stringify({ lojaLocal: new URLSearchParams(window.location.search).get("loja") || undefined }),
          cache: "no-store",
        });
        const dados = (await resposta.json().catch(() => null)) as { endereco?: string } | null;
        if (!vivo) return;
        if (resposta.status === 409) setPrevia({ indisponivel: "sem-loja" });
        else if (resposta.ok && dados?.endereco) setPrevia({ endereco: dados.endereco });
        else setPrevia((atual) => (atual && "endereco" in atual ? atual : { indisponivel: "falhou" }));
      } catch {
        if (vivo) setPrevia((atual) => (atual && "endereco" in atual ? atual : { indisponivel: "falhou" }));
      }
    };
    void pedir();
    const renovar = window.setInterval(() => void pedir(), RENOVAR_A_CADA_MS);
    return () => {
      vivo = false;
      window.clearInterval(renovar);
    };
  }, []);
  return previa;
}

function enderecoDoTema(endereco: string, tema: TemaDoCartao) {
  return `${endereco}&tema=${encodeURIComponent(tema)}`;
}

/* O esqueleto do quadro enquanto a loja carrega: o contorno de uma home. */
function EsqueletoDaLoja() {
  return (
    <div className="absolute inset-0 flex animate-pulse flex-col gap-[6%] bg-[var(--ks-n-50)] p-[5%]" aria-hidden>
      <div className="flex items-center gap-[4%]">
        <div className="h-3 w-[18%] rounded-full bg-[var(--ks-n-200)]" />
        <div className="h-2 flex-1 rounded-full bg-[var(--ks-n-150)]" />
        <div className="h-3 w-[8%] rounded-full bg-[var(--ks-n-200)]" />
      </div>
      <div className="h-[34%] rounded-lg bg-[var(--ks-n-150)]" />
      <div className="grid flex-1 grid-cols-4 gap-[4%]">
        {[0, 1, 2, 3].map((i) => (
          <div key={i} className="rounded-md bg-[var(--ks-n-150)]" />
        ))}
      </div>
    </div>
  );
}

function SemPrevia({ tema, motivo }: { tema: TemaDoCartao; motivo: "sem-loja" | "falhou" | "demorou" }) {
  const Icone = motivo === "sem-loja" ? THEME_ICONS[tema] : ImageOff;
  return (
    <div className="absolute inset-0 flex flex-col items-center justify-center gap-2 bg-[var(--ks-n-50)] px-4 text-center">
      <span
        className="flex h-10 w-10 items-center justify-center rounded-xl text-white"
        style={{ background: "linear-gradient(135deg, var(--ks-brand-500) 0%, var(--ks-brand-700) 100%)" }}
      >
        <Icone size={18} />
      </span>
      <p className="text-xs font-medium leading-snug text-[var(--ks-color-text-muted)]">
        {motivo === "sem-loja" ? "Defina o link da loja para ver a prévia." : "Não deu para mostrar a prévia agora."}
      </p>
    </div>
  );
}

function QuadroDaLoja({ tema, endereco }: { tema: TemaDoCartao; endereco: string }) {
  const caixa = useRef<HTMLDivElement>(null);
  const [escala, setEscala] = useState(0);
  const [visivel, setVisivel] = useState(() => typeof IntersectionObserver === "undefined");
  /* O endereço do quadro fica preso ao primeiro: a passagem renovada não recarrega a loja. */
  const [enderecoDoQuadro] = useState(endereco);
  const src = visivel ? enderecoDoTema(enderecoDoQuadro, tema) : null;
  const [estado, setEstado] = useState<"carregando" | "pronto" | "demorou">("carregando");

  useEffect(() => {
    const alvo = caixa.current;
    if (!alvo) return;
    const medir = () => setEscala(alvo.clientWidth / LARGURA_DA_TELA);
    /* A régua já mede ao começar a observar. */
    const regua = typeof ResizeObserver !== "undefined" ? new ResizeObserver(medir) : null;
    regua?.observe(alvo);
    const primeiraMedida = regua ? 0 : window.requestAnimationFrame(medir);
    /* Só carrega a loja quando o cartão chega perto da tela. */
    if (typeof IntersectionObserver === "undefined") {
      return () => {
        regua?.disconnect();
        window.cancelAnimationFrame(primeiraMedida);
      };
    }
    const vigia = new IntersectionObserver(
      (entradas) => {
        if (entradas.some((entrada) => entrada.isIntersecting)) {
          setVisivel(true);
          vigia.disconnect();
        }
      },
      { rootMargin: "200px 0px" }
    );
    vigia.observe(alvo);
    return () => {
      regua?.disconnect();
      vigia.disconnect();
    };
  }, []);

  useEffect(() => {
    if (!src || estado !== "carregando") return;
    const relogio = window.setTimeout(() => setEstado("demorou"), ESPERA_DO_QUADRO_MS);
    return () => window.clearTimeout(relogio);
  }, [src, estado]);

  return (
    <div ref={caixa} className="absolute inset-0 overflow-hidden">
      {src && escala > 0 ? (
        <iframe
          src={src}
          title=""
          aria-hidden
          tabIndex={-1}
          loading="lazy"
          scrolling="no"
          referrerPolicy="no-referrer"
          sandbox="allow-scripts allow-same-origin"
          onLoad={() => setEstado("pronto")}
          className={`pointer-events-none absolute left-0 top-0 origin-top-left border-0 bg-white transition-opacity duration-500 ${
            estado === "pronto" ? "opacity-100" : "opacity-0"
          }`}
          style={{ width: LARGURA_DA_TELA, height: ALTURA_DA_TELA, transform: `scale(${escala})` }}
        />
      ) : null}
      {estado === "carregando" ? <EsqueletoDaLoja /> : null}
      {estado === "demorou" ? <SemPrevia tema={tema} motivo="demorou" /> : null}
    </div>
  );
}

export default function ThemeSelector({
  value,
  onChange,
}: {
  value: "default" | "neo" | "vitrine" | "vendor" | "boutique";
  onChange: (value: "default" | "neo" | "vitrine" | "vendor" | "boutique") => void;
}) {
  const previa = usePreviaDaLoja();
  const endereco = previa && "endereco" in previa ? previa.endereco : null;

  return (
    <div className="@container">
      <div role="radiogroup" aria-label="Template da loja" className="grid grid-cols-1 gap-4 @xl:grid-cols-2 @5xl:grid-cols-4">
        {THEME_OPTIONS.map((option) => {
          const active = value === option.value || (value === "neo" && option.value === "default"); // Fallback for neo
          return (
            <div
              key={option.value}
              className={`group relative flex flex-col overflow-hidden rounded-2xl border bg-[var(--ks-color-bg-elevated)] transition-[border-color,box-shadow] ${
                active
                  ? "border-[var(--ks-brand-500)] shadow-[0_0_0_3px_var(--ks-brand-100),0_12px_28px_-18px_rgba(95,49,214,0.55)]"
                  : "border-[var(--ks-color-border-subtle)] hover:border-[var(--ks-n-300)]"
              }`}
            >
              {/* A loja de verdade, neste tema. O quadro não recebe clique
                  (pointer-events: none): o clique cai aqui e escolhe o tema;
                  pelo teclado, a escolha é o rádio logo abaixo. */}
              <div
                aria-hidden
                onClick={() => onChange(option.value)}
                className="relative aspect-[16/10] w-full cursor-pointer overflow-hidden border-b border-[var(--ks-color-border-subtle)] bg-[var(--ks-n-50)]"
              >
                {endereco ? (
                  <QuadroDaLoja tema={option.value} endereco={endereco} />
                ) : previa ? (
                  <SemPrevia tema={option.value} motivo={"indisponivel" in previa ? previa.indisponivel : "falhou"} />
                ) : (
                  <EsqueletoDaLoja />
                )}
              </div>
              <button
                type="button"
                role="radio"
                aria-checked={active}
                onClick={() => onChange(option.value)}
                className="flex flex-1 flex-col text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--ks-brand-500)]"
              >
                <span className="flex flex-1 items-start gap-3 px-4 pb-4 pt-3.5">
                  <span
                    aria-hidden
                    className={`mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors ${
                      active ? "border-[var(--ks-brand-600)] bg-[var(--ks-brand-600)] text-white" : "border-[var(--ks-n-300)] bg-white"
                    }`}
                  >
                    {active ? <Check size={12} strokeWidth={3} /> : null}
                  </span>
                  <span className="min-w-0">
                    <span className="flex items-center gap-2">
                      <span className={`text-sm font-bold ${active ? "text-[var(--ks-brand-600)]" : "text-[var(--ks-color-text-primary)]"}`}>
                        {option.label}
                      </span>
                      {active ? (
                        <span className="rounded-full bg-[var(--ks-brand-600)] px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-white">
                          Escolhido
                        </span>
                      ) : null}
                    </span>
                    <span className="mt-1 block text-xs leading-relaxed text-[var(--ks-color-text-muted)]">{option.description}</span>
                  </span>
                </span>
              </button>
              {endereco ? (
                <a
                  href={enderecoDoTema(endereco, option.value)}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="absolute right-2.5 top-2.5 z-10 inline-flex items-center gap-1 rounded-full bg-white/95 px-2.5 py-1 text-[11px] font-semibold text-[var(--ks-color-text-primary)] opacity-0 shadow-[0_4px_14px_-6px_rgba(15,23,42,0.45)] ring-1 ring-black/5 backdrop-blur transition-opacity hover:text-[var(--ks-brand-600)] focus-visible:opacity-100 group-hover:opacity-100 [@media(hover:none)]:opacity-100"
                >
                  Ver em tela cheia
                  <ArrowUpRight size={12} strokeWidth={2.5} />
                </a>
              ) : null}
            </div>
          );
        })}
      </div>
    </div>
  );
}
