"use client";

import { useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { Check, ChevronDown, Search, X } from "lucide-react";
import ImageUpload from "@/components/image-upload";
import { Switch } from "@/components/ui/switch";
import { problemaDoEndereco, type LinkDaSecao, type TipoDeLink } from "@/lib/pagina-inicial";

/*
  Os controles do painel de ajustes da seção. Estreitos (o painel tem 360 px)
  e no desenho da casa: rótulo pequeno em cima, controle embaixo, divisória
  quase invisível entre um ajuste e outro.
*/

export type ProdutoDoEditor = {
  id: string;
  name: string;
  price: number;
  image_url?: string | null;
  category_id?: string | null;
};

export type CategoriaDoEditor = { id: string; name: string; slug: string; parent_id?: string | null };

export function Ajuste({ rotulo, dica, children, direita }: { rotulo: string; dica?: ReactNode; children: ReactNode; direita?: ReactNode }) {
  return (
    <div className="border-t border-[var(--ks-n-100)] px-5 py-4 first:border-t-0">
      <div className="mb-2.5 flex items-center justify-between gap-3">
        <span className="text-[12px] font-bold text-[var(--ks-color-text-primary)]">{rotulo}</span>
        {direita}
      </div>
      {children}
      {dica ? <p className="mt-2 text-[11.5px] leading-[1.45] text-[var(--ks-color-text-soft)]">{dica}</p> : null}
    </div>
  );
}

/** Opções curtas lado a lado (alinhamento, tamanho, espaço). */
export function Segmentos<T extends string>({
  valor,
  opcoes,
  aoMudar,
  rotulo,
}: {
  valor: T;
  opcoes: Array<{ valor: T; rotulo: ReactNode; titulo?: string }>;
  aoMudar: (valor: T) => void;
  rotulo?: string;
}) {
  return (
    <div role="radiogroup" aria-label={rotulo} className="flex w-full rounded-xl bg-[var(--ks-color-bg-inset)] p-1">
      {opcoes.map((opcao) => {
        const ativo = opcao.valor === valor;
        return (
          <button
            key={opcao.valor}
            type="button"
            role="radio"
            aria-checked={ativo}
            title={opcao.titulo}
            onClick={() => aoMudar(opcao.valor)}
            className={`flex min-h-[34px] flex-1 items-center justify-center gap-1.5 rounded-lg px-2 text-[12px] font-semibold transition ${
              ativo
                ? "bg-[var(--ks-color-bg-elevated)] text-[var(--ks-color-primary)] shadow-[0_2px_8px_rgba(45,30,105,0.12)]"
                : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
            }`}
          >
            {opcao.rotulo}
          </button>
        );
      })}
    </div>
  );
}

/** Opções com desenho (formato do banner, arrumação das imagens). */
export function Miniaturas<T extends string>({
  valor,
  opcoes,
  aoMudar,
  colunas = 3,
}: {
  valor: T;
  opcoes: Array<{ valor: T; nome: string; detalhe?: string; desenho: ReactNode }>;
  aoMudar: (valor: T) => void;
  colunas?: 2 | 3 | 4;
}) {
  return (
    <div role="radiogroup" className={`grid gap-2 ${colunas === 2 ? "grid-cols-2" : colunas === 4 ? "grid-cols-4" : "grid-cols-3"}`}>
      {opcoes.map((opcao) => {
        const ativo = opcao.valor === valor;
        return (
          <button
            key={opcao.valor}
            type="button"
            role="radio"
            aria-checked={ativo}
            onClick={() => aoMudar(opcao.valor)}
            className={`group flex flex-col items-center gap-1.5 rounded-xl border px-1.5 pb-2 pt-2.5 transition ${
              ativo
                ? "border-[var(--ks-color-primary)] bg-[var(--ks-brand-50)] text-[var(--ks-color-primary)]"
                : "border-[var(--ks-color-border-subtle)] text-[var(--ks-n-400)] hover:border-[var(--ks-brand-300)] hover:text-[var(--ks-brand-500)]"
            }`}
          >
            <span className="flex h-9 w-full items-center justify-center">{opcao.desenho}</span>
            <span className={`text-[11px] font-bold leading-tight ${ativo ? "" : "text-[var(--ks-color-text-secondary)]"}`}>{opcao.nome}</span>
            {opcao.detalhe ? <span className="-mt-1 text-[10px] font-medium text-[var(--ks-color-text-soft)]">{opcao.detalhe}</span> : null}
          </button>
        );
      })}
    </div>
  );
}

/** O desenho de uma proporção: um retângulo com aquela forma. */
export function DesenhoDaProporcao({ proporcao }: { proporcao: number }) {
  const largura = proporcao >= 1 ? 40 : Math.round(30 * proporcao);
  const altura = proporcao >= 1 ? Math.max(5, Math.round(40 / proporcao)) : 30;
  return <span className="block rounded-[4px] bg-current opacity-80" style={{ width: largura, height: Math.min(30, altura) }} />;
}

export function Chave({ ligada, aoMudar, rotulo, dica }: { ligada: boolean; aoMudar: (ligada: boolean) => void; rotulo: string; dica?: string }) {
  return (
    <div className="flex items-start justify-between gap-4 border-t border-[var(--ks-n-100)] px-5 py-3.5 first:border-t-0">
      <div className="min-w-0">
        <p className="text-[12.5px] font-semibold text-[var(--ks-color-text-primary)]">{rotulo}</p>
        {dica ? <p className="mt-0.5 text-[11.5px] leading-[1.45] text-[var(--ks-color-text-soft)]">{dica}</p> : null}
      </div>
      <Switch checked={ligada} onCheckedChange={aoMudar} aria-label={rotulo} />
    </div>
  );
}

export function Texto({
  valor,
  aoMudar,
  placeholder,
  max = 120,
  rotulo,
}: {
  valor: string;
  aoMudar: (valor: string) => void;
  placeholder?: string;
  max?: number;
  rotulo?: string;
}) {
  return (
    <input
      value={valor}
      onChange={(e) => aoMudar(e.target.value.slice(0, max))}
      placeholder={placeholder}
      aria-label={rotulo}
      className="w-full rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] px-3 text-[13px] text-[var(--ks-color-text-primary)] outline-none transition placeholder:text-[var(--ks-color-text-soft)] focus:border-[var(--ks-color-primary)] focus:shadow-[var(--ks-focus-ring)]"
      style={{ height: 38 }}
    />
  );
}

export function CampoDeImagem({
  valor,
  aoMudar,
  proporcao,
  largura,
  altura,
  dica,
}: {
  valor: string;
  aoMudar: (url: string) => void;
  proporcao: number;
  largura: number;
  altura: number;
  dica?: string;
}) {
  return (
    <ImageUpload
      bucket="products"
      folder="catalog/sections/pagina-inicial"
      value={valor}
      onChange={aoMudar}
      enableCrop
      cropAspect={proporcao}
      visual={{ proporcao, dica: dica || `Ideal ${largura} × ${altura} px. Você recorta depois de escolher.` }}
    />
  );
}

/** A lista que abre ao tocar: busca no topo, opções embaixo. */
export function Escolha<T extends { id: string }>({
  valor,
  itens,
  aoEscolher,
  textoDoItem,
  detalheDoItem,
  fotoDoItem,
  placeholder,
  vazio,
}: {
  valor: string | null | undefined;
  itens: T[];
  aoEscolher: (item: T) => void;
  textoDoItem: (item: T) => string;
  detalheDoItem?: (item: T) => string;
  fotoDoItem?: (item: T) => string | null | undefined;
  placeholder: string;
  vazio?: string;
}) {
  const [aberta, setAberta] = useState(false);
  const [busca, setBusca] = useState("");
  const caixa = useRef<HTMLDivElement | null>(null);
  const escolhido = itens.find((item) => item.id === valor) || null;

  useEffect(() => {
    if (!aberta) return;
    const fora = (evento: MouseEvent) => {
      if (!caixa.current?.contains(evento.target as Node)) setAberta(false);
    };
    document.addEventListener("mousedown", fora);
    return () => document.removeEventListener("mousedown", fora);
  }, [aberta]);

  const filtrados = useMemo(() => {
    const termo = busca
      .normalize("NFD")
      .replace(/[̀-ͯ]/g, "")
      .toLowerCase()
      .trim();
    const lista = termo
      ? itens.filter((item) =>
          textoDoItem(item)
            .normalize("NFD")
            .replace(/[̀-ͯ]/g, "")
            .toLowerCase()
            .includes(termo)
        )
      : itens;
    return lista.slice(0, 80);
  }, [busca, itens, textoDoItem]);

  return (
    <div ref={caixa} className="relative">
      <button
        type="button"
        onClick={() => setAberta((a) => !a)}
        className="flex h-[38px] w-full items-center gap-2 rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] px-3 text-left text-[13px] transition hover:border-[var(--ks-brand-300)]"
      >
        {escolhido && fotoDoItem?.(escolhido) ? (
          /* eslint-disable-next-line @next/next/no-img-element */
          <img src={fotoDoItem(escolhido) as string} alt="" className="h-6 w-6 rounded-md object-cover" />
        ) : null}
        <span className={`min-w-0 flex-1 truncate ${escolhido ? "font-semibold text-[var(--ks-color-text-primary)]" : "text-[var(--ks-color-text-soft)]"}`}>
          {escolhido ? textoDoItem(escolhido) : placeholder}
        </span>
        <ChevronDown size={15} className="shrink-0 text-[var(--ks-color-text-soft)]" />
      </button>
      {aberta ? (
        <div className="absolute left-0 right-0 top-[calc(100%+6px)] z-[80] overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] shadow-[var(--ks-shadow-overlay)]">
          <div className="flex items-center gap-2 border-b border-[var(--ks-n-100)] px-3">
            <Search size={14} className="text-[var(--ks-color-text-soft)]" />
            <input
              autoFocus
              value={busca}
              onChange={(e) => setBusca(e.target.value)}
              placeholder="Buscar"
              className="h-10 flex-1 bg-transparent text-[13px] outline-none"
            />
          </div>
          <div className="max-h-64 overflow-y-auto py-1">
            {filtrados.length ? (
              filtrados.map((item) => (
                <button
                  key={item.id}
                  type="button"
                  onClick={() => {
                    aoEscolher(item);
                    setAberta(false);
                    setBusca("");
                  }}
                  className="flex w-full items-center gap-2.5 px-3 py-2 text-left transition hover:bg-[var(--ks-color-bg-hover)]"
                >
                  {fotoDoItem ? (
                    fotoDoItem(item) ? (
                      /* eslint-disable-next-line @next/next/no-img-element */
                      <img src={fotoDoItem(item) as string} alt="" className="h-8 w-8 shrink-0 rounded-lg object-cover" />
                    ) : (
                      <span className="h-8 w-8 shrink-0 rounded-lg bg-[var(--ks-color-bg-inset)]" />
                    )
                  ) : null}
                  <span className="min-w-0 flex-1">
                    <span className="block truncate text-[13px] font-semibold text-[var(--ks-color-text-primary)]">{textoDoItem(item)}</span>
                    {detalheDoItem ? <span className="block truncate text-[11px] text-[var(--ks-color-text-soft)]">{detalheDoItem(item)}</span> : null}
                  </span>
                  {item.id === valor ? <Check size={15} className="shrink-0 text-[var(--ks-color-primary)]" /> : null}
                </button>
              ))
            ) : (
              <p className="px-3 py-4 text-center text-[12px] text-[var(--ks-color-text-soft)]">{vazio || "Nada encontrado."}</p>
            )}
          </div>
        </div>
      ) : null}
    </div>
  );
}

export function nomeDaCategoria(categoria: CategoriaDoEditor, todas: CategoriaDoEditor[]) {
  const pai = categoria.parent_id ? todas.find((c) => c.id === categoria.parent_id) : null;
  return pai ? `${pai.name} › ${categoria.name}` : categoria.name;
}

const moeda = new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" });
export function emReais(valor: number) {
  return moeda.format(Number(valor) || 0);
}

/** Para onde vai o clique numa imagem ou banner. */
export function CampoDeLink({
  link,
  aoMudar,
  produtos,
  categorias,
}: {
  link: LinkDaSecao;
  aoMudar: (link: LinkDaSecao) => void;
  produtos: ProdutoDoEditor[];
  categorias: CategoriaDoEditor[];
}) {
  const problema = link.tipo === "url" && link.url ? problemaDoEndereco(link.url) : null;
  return (
    <div className="space-y-2.5">
      <Segmentos<TipoDeLink>
        rotulo="Para onde o clique leva"
        valor={link.tipo}
        aoMudar={(tipo) => aoMudar({ tipo, nova_aba: link.nova_aba })}
        opcoes={[
          { valor: "nenhum", rotulo: "Nenhum" },
          { valor: "produto", rotulo: "Produto" },
          { valor: "categoria", rotulo: "Categoria" },
          { valor: "url", rotulo: "Endereço" },
        ]}
      />
      {link.tipo === "produto" ? (
        <Escolha
          valor={link.produto_id}
          itens={produtos}
          aoEscolher={(produto) => aoMudar({ tipo: "produto", produto_id: produto.id })}
          textoDoItem={(produto) => produto.name}
          detalheDoItem={(produto) => emReais(produto.price)}
          fotoDoItem={(produto) => produto.image_url}
          placeholder="Escolher o produto"
          vazio="Nenhum produto na loja com esse nome."
        />
      ) : null}
      {link.tipo === "categoria" ? (
        <Escolha
          valor={link.categoria_id}
          itens={categorias}
          aoEscolher={(categoria) => aoMudar({ tipo: "categoria", categoria_id: categoria.id, categoria_slug: categoria.slug })}
          textoDoItem={(categoria) => nomeDaCategoria(categoria, categorias)}
          placeholder="Escolher a categoria"
          vazio="Nenhuma categoria visível com esse nome."
        />
      ) : null}
      {link.tipo === "url" ? (
        <>
          <Texto
            valor={link.url || ""}
            aoMudar={(url) => aoMudar({ ...link, url })}
            placeholder="https://... ou /minha-loja/c/canecas"
            max={500}
            rotulo="Endereço do link"
          />
          {problema ? <p className="text-[11.5px] font-semibold text-[var(--ks-color-status-danger)]">{problema}</p> : null}
          <label className="flex cursor-pointer items-center gap-2 text-[12px] text-[var(--ks-color-text-secondary)]">
            <input
              type="checkbox"
              checked={link.nova_aba === true}
              onChange={(e) => aoMudar({ ...link, nova_aba: e.target.checked })}
              className="h-4 w-4 accent-[var(--ks-color-primary)]"
            />
            Abrir em outra aba
          </label>
        </>
      ) : null}
    </div>
  );
}

/** A lista de produtos escolhidos: ordem, tirar e pôr. */
export function ListaDeProdutos({
  ids,
  aoMudar,
  produtos,
  limite,
}: {
  ids: string[];
  aoMudar: (ids: string[]) => void;
  produtos: ProdutoDoEditor[];
  limite: number;
}) {
  const [busca, setBusca] = useState("");
  const porId = useMemo(() => new Map(produtos.map((p) => [p.id, p])), [produtos]);
  const escolhidos = ids.map((id) => porId.get(id)).filter((p): p is ProdutoDoEditor => Boolean(p));
  const termo = busca.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
  const sugestoes = termo
    ? produtos
        .filter((p) => !ids.includes(p.id))
        .filter((p) => p.name.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().includes(termo))
        .slice(0, 8)
    : [];

  return (
    <div className="space-y-3">
      <div className="relative">
        <Search size={14} className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[var(--ks-color-text-soft)]" />
        <input
          value={busca}
          onChange={(e) => setBusca(e.target.value)}
          placeholder={ids.length >= limite ? `Limite de ${limite} produtos` : "Buscar produto para pôr"}
          disabled={ids.length >= limite}
          className="h-[38px] w-full rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] pl-9 pr-3 text-[13px] outline-none focus:border-[var(--ks-color-primary)] disabled:opacity-60"
        />
        {sugestoes.length ? (
          <div className="absolute left-0 right-0 top-[calc(100%+6px)] z-[80] overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] py-1 shadow-[var(--ks-shadow-overlay)]">
            {sugestoes.map((produto) => (
              <button
                key={produto.id}
                type="button"
                onClick={() => {
                  aoMudar([...ids, produto.id]);
                  setBusca("");
                }}
                className="flex w-full items-center gap-2.5 px-3 py-2 text-left hover:bg-[var(--ks-color-bg-hover)]"
              >
                {produto.image_url ? (
                  /* eslint-disable-next-line @next/next/no-img-element */
                  <img src={produto.image_url} alt="" className="h-8 w-8 rounded-lg object-cover" />
                ) : (
                  <span className="h-8 w-8 rounded-lg bg-[var(--ks-color-bg-inset)]" />
                )}
                <span className="min-w-0 flex-1 truncate text-[13px] font-semibold">{produto.name}</span>
                <span className="text-[11px] text-[var(--ks-color-text-soft)]">{emReais(produto.price)}</span>
              </button>
            ))}
          </div>
        ) : null}
      </div>
      {escolhidos.length ? (
        <ol className="overflow-hidden rounded-xl border border-[var(--ks-color-border-subtle)]">
          {escolhidos.map((produto, indice) => (
            <li key={produto.id} className="flex items-center gap-2.5 border-t border-[var(--ks-n-100)] px-2.5 py-2 first:border-t-0">
              <span className="w-5 text-center text-[11px] font-bold tabular-nums text-[var(--ks-color-text-soft)]">{indice + 1}</span>
              {produto.image_url ? (
                /* eslint-disable-next-line @next/next/no-img-element */
                <img src={produto.image_url} alt="" className="h-8 w-8 rounded-lg object-cover" />
              ) : (
                <span className="h-8 w-8 rounded-lg bg-[var(--ks-color-bg-inset)]" />
              )}
              <span className="min-w-0 flex-1 truncate text-[12.5px] font-semibold text-[var(--ks-color-text-primary)]">{produto.name}</span>
              <span className="flex items-center">
                <button
                  type="button"
                  aria-label="Subir"
                  disabled={indice === 0}
                  onClick={() => {
                    const nova = [...ids];
                    const i = nova.indexOf(produto.id);
                    [nova[i - 1], nova[i]] = [nova[i], nova[i - 1]];
                    aoMudar(nova);
                  }}
                  className="flex h-7 w-7 items-center justify-center rounded-lg text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)] hover:text-[var(--ks-color-primary)] disabled:opacity-30"
                >
                  <ChevronDown size={15} className="rotate-180" />
                </button>
                <button
                  type="button"
                  aria-label="Descer"
                  disabled={indice === escolhidos.length - 1}
                  onClick={() => {
                    const nova = [...ids];
                    const i = nova.indexOf(produto.id);
                    [nova[i + 1], nova[i]] = [nova[i], nova[i + 1]];
                    aoMudar(nova);
                  }}
                  className="flex h-7 w-7 items-center justify-center rounded-lg text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-hover)] hover:text-[var(--ks-color-primary)] disabled:opacity-30"
                >
                  <ChevronDown size={15} />
                </button>
                <button
                  type="button"
                  aria-label="Tirar da seção"
                  onClick={() => aoMudar(ids.filter((id) => id !== produto.id))}
                  className="flex h-7 w-7 items-center justify-center rounded-lg text-[var(--ks-color-text-soft)] hover:bg-rose-50 hover:text-rose-600"
                >
                  <X size={15} />
                </button>
              </span>
            </li>
          ))}
        </ol>
      ) : (
        <p className="rounded-xl bg-[var(--ks-color-bg-inset)] px-3 py-4 text-center text-[12px] text-[var(--ks-color-text-soft)]">
          Busque acima e toque no produto para pôr na seção.
        </p>
      )}
    </div>
  );
}
