"use client";

import type { LucideIcon } from "lucide-react";
import { useEffect, useState, type ReactNode, type TextareaHTMLAttributes } from "react";
import { motion, useReducedMotion } from "framer-motion";
import { Switch } from "@/components/ui/switch";

/**
 * A folha de ajustes: o padrão de tela de configuração do painel.
 *
 * Nasceu na aba "Regras da loja" (08/10/2026), depois que o Natan recusou a
 * versão em caixas: "muito seco, boxes engessados". Em vez de um cartão por
 * regra e uma grade de caixas por opção, uma folha corrida: as seções
 * separadas por um fio, cada ajuste numa linha com o nome e a explicação à
 * esquerda e o controle à direita, as opções como rádio em lista, e um índice
 * fixo ao lado que diz, de relance, o que está escolhido em cada parte e
 * marca a parte em que a pessoa está.
 *
 * Só desenho: quem usa continua dono do estado e do salvar. Serve para
 * qualquer tela de ajustes (Personalização, Logística, Configurações).
 */

export type ItemDoIndice = {
  id: string;
  titulo: string;
  /** O que está escolhido nessa parte, numa frase curta. */
  resumo: string;
  Icone: LucideIcon;
  /** Diferente do padrão: ganha um ponto violeta no índice. */
  mexido?: boolean;
};

/** A régua quase invisível entre as linhas de uma seção (também para listas). */
export const FIO_DA_LINHA = "border-t border-[var(--ks-n-100)] first:border-t-0";
const COLUNAS_DA_LINHA = "md:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]";

export function FolhaDeAjustes({
  indice,
  rotuloDoIndice = "Nesta tela",
  children,
}: {
  indice?: ItemDoIndice[];
  rotuloDoIndice?: string;
  children: ReactNode;
}) {
  const temIndice = Boolean(indice?.length);
  return (
    <div className={temIndice ? "grid gap-5 lg:grid-cols-[224px_minmax(0,1fr)] lg:items-start lg:gap-8" : ""}>
      {temIndice ? <IndiceDeAjustes itens={indice ?? []} rotulo={rotuloDoIndice} /> : null}
      <div className="min-w-0 overflow-hidden rounded-2xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] shadow-[var(--ks-shadow-subtle)]">
        {children}
      </div>
    </div>
  );
}

/*
  A seção "atual" é a primeira (na ordem da folha) que cruza a faixa de
  leitura, entre 15% e 40% da altura da janela. Observar as seções em vez de
  ouvir o scroll funciona igual com a janela ou um container rolando, e não
  roda a cada pixel. Seções que entram depois (um bloco que carrega sozinho)
  são apanhadas numa segunda passada.
*/
function useSecaoAtual(ids: string[]) {
  const [atual, setAtual] = useState<string | null>(ids[0] ?? null);
  const chave = ids.join("|");
  useEffect(() => {
    if (typeof IntersectionObserver === "undefined") return;
    const lista = chave ? chave.split("|") : [];
    const visiveis = new Set<string>();
    const observador = new IntersectionObserver(
      (entradas) => {
        for (const entrada of entradas) {
          if (entrada.isIntersecting) visiveis.add(entrada.target.id);
          else visiveis.delete(entrada.target.id);
        }
        const primeira = lista.find((id) => visiveis.has(id));
        if (primeira) setAtual(primeira);
      },
      { rootMargin: "-15% 0px -60% 0px", threshold: 0 }
    );
    const observadas = new Set<string>();
    const observar = () => {
      for (const id of lista) {
        if (observadas.has(id)) continue;
        const alvo = document.getElementById(id);
        if (!alvo) continue;
        observador.observe(alvo);
        observadas.add(id);
      }
    };
    observar();
    const segundaPassada = window.setTimeout(observar, 1500);
    return () => {
      window.clearTimeout(segundaPassada);
      observador.disconnect();
    };
  }, [chave]);
  return [atual, setAtual] as const;
}

/* No computador o índice fica preso ao lado, com o resumo de cada parte; no
   celular vira uma fila de atalhos que rola de lado, só com o nome. */
function IndiceDeAjustes({ itens, rotulo }: { itens: ItemDoIndice[]; rotulo: string }) {
  const [atual, setAtual] = useSecaoAtual(itens.map((item) => item.id));
  const irPara = (id: string) => {
    setAtual(id);
    const alvo = document.getElementById(id);
    if (!alvo) return;
    alvo.scrollIntoView({ behavior: "smooth", block: "start" });
  };
  return (
    <nav aria-label={rotulo} className="min-w-0 lg:sticky lg:top-24">
      <p className="hidden px-3 pb-2 text-[11px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)] lg:block">{rotulo}</p>
      <ul className="-mx-1 flex gap-1 overflow-x-auto px-1 pb-1 lg:mx-0 lg:flex-col lg:gap-0.5 lg:overflow-visible lg:px-0 lg:pb-0">
        {itens.map(({ id, titulo, resumo, Icone, mexido }) => {
          const ativo = atual === id;
          return (
            <li key={id} className="shrink-0 lg:shrink">
              <a
                href={`#${id}`}
                aria-current={ativo ? "location" : undefined}
                onClick={(evento) => {
                  evento.preventDefault();
                  irPara(id);
                }}
                className={`flex items-center gap-2.5 rounded-xl px-3 py-2 transition-colors lg:items-start lg:py-2.5 ${
                  ativo ? "bg-[var(--ks-brand-50)]" : "hover:bg-[var(--ks-color-bg-hover)]"
                }`}
              >
                <span
                  className={`flex h-6 w-6 shrink-0 items-center justify-center transition-colors lg:mt-px ${
                    ativo ? "text-[var(--ks-brand-600)]" : "text-[var(--ks-color-text-soft)]"
                  }`}
                >
                  <Icone size={16} />
                </span>
                <span className="min-w-0">
                  <span
                    className={`flex items-center gap-1.5 whitespace-nowrap text-[13px] ${
                      ativo ? "font-bold text-[var(--ks-brand-600)]" : "font-semibold text-[var(--ks-color-text-primary)]"
                    }`}
                  >
                    {titulo}
                    {mexido ? <span aria-label="diferente do padrão" className="h-1.5 w-1.5 rounded-full bg-[var(--ks-brand-500)]" /> : null}
                  </span>
                  <span className="hidden truncate text-xs text-[var(--ks-color-text-muted)] lg:block" title={resumo}>
                    {resumo}
                  </span>
                </span>
              </a>
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

/**
 * Uma seção da folha: selo violeta, título e uma frase; à direita, quando
 * precisa, uma ação (um botão, uma chave). As linhas vêm dentro.
 */
export function SecaoDeAjustes({
  id,
  Icone,
  titulo,
  texto,
  acao,
  children,
}: {
  id: string;
  Icone: LucideIcon;
  titulo: ReactNode;
  texto?: ReactNode;
  acao?: ReactNode;
  children: ReactNode;
}) {
  return (
    <section id={id} className="scroll-mt-24 border-t border-[var(--ks-color-border-subtle)] px-5 pb-2 pt-5 first:border-t-0 sm:px-6">
      <header className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4">
        <div className="flex min-w-0 items-start gap-3">
          <span
            className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl text-white"
            style={{ background: "linear-gradient(135deg, var(--ks-brand-500) 0%, var(--ks-brand-700) 100%)", boxShadow: "0 6px 16px rgba(95, 49, 214, 0.24)" }}
          >
            <Icone size={18} />
          </span>
          <div className="min-w-0">
            <h3 className="text-[15px] font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">{titulo}</h3>
            {texto ? <p className="mt-0.5 text-[13px] leading-5 text-[var(--ks-color-text-muted)]">{texto}</p> : null}
          </div>
        </div>
        {acao ? <div className="shrink-0 sm:pt-0.5">{acao}</div> : null}
      </header>
      <div className="mt-2">{children}</div>
    </section>
  );
}

/**
 * Um ajuste: nome e explicação à esquerda, o controle à direita. `largo`
 * põe o nome em cima e o controle na largura toda (grades de cores, prévias).
 */
export function LinhaDeAjuste({
  titulo,
  texto,
  htmlFor,
  largo = false,
  children,
}: {
  titulo: string;
  texto?: ReactNode;
  /** O campo que o nome rotula (vira <label>). */
  htmlFor?: string;
  largo?: boolean;
  children: ReactNode;
}) {
  const classeDoNome = "block text-sm font-semibold text-[var(--ks-color-text-primary)]";
  return (
    <div className={`grid gap-x-8 gap-y-2.5 py-4 md:items-start ${largo ? "" : COLUNAS_DA_LINHA} ${FIO_DA_LINHA}`}>
      <div className={`min-w-0 ${largo ? "" : "md:pt-1.5"}`}>
        {htmlFor ? (
          <label htmlFor={htmlFor} className={classeDoNome}>
            {titulo}
          </label>
        ) : (
          <span className={classeDoNome}>{titulo}</span>
        )}
        {texto ? <p className="mt-0.5 text-xs leading-relaxed text-[var(--ks-color-text-muted)]">{texto}</p> : null}
      </div>
      <div className="min-w-0">{children}</div>
    </div>
  );
}

/** Liga/desliga numa linha: nome à esquerda, a chave na ponta direita. */
export function ChaveDeAjuste({
  titulo,
  texto,
  ligado,
  aoMudar,
  desabilitado = false,
}: {
  titulo: string;
  texto?: ReactNode;
  ligado: boolean;
  aoMudar: (ligado: boolean) => void;
  desabilitado?: boolean;
}) {
  return (
    <div className={`flex items-start justify-between gap-4 py-3.5 ${FIO_DA_LINHA}`}>
      <div className="min-w-0">
        <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">{titulo}</p>
        {texto ? <p className="mt-0.5 text-xs leading-relaxed text-[var(--ks-color-text-muted)]">{texto}</p> : null}
      </div>
      <div className="flex shrink-0 items-center gap-2.5 pt-0.5">
        <span className={`text-xs font-semibold ${ligado ? "text-[var(--ks-color-primary)]" : "text-[var(--ks-color-text-soft)]"}`}>
          {ligado ? "Ligado" : "Desligado"}
        </span>
        <Switch checked={ligado} disabled={desabilitado} onCheckedChange={aoMudar} aria-label={titulo} />
      </div>
    </div>
  );
}

/**
 * Uma escolha entre poucas opções, em lista: rádio, nome e uma linha de
 * explicação por opção. A escolhida ganha o rádio cheio e um fundo leve.
 */
export function EscolhaDeAjuste<T extends string>({
  rotulo,
  valor,
  aoEscolher,
  opcoes,
  ajuda,
}: {
  rotulo: string;
  valor: T;
  aoEscolher: (valor: T) => void;
  opcoes: { valor: T; titulo: string; texto?: string }[];
  ajuda?: ReactNode;
}) {
  const parado = useReducedMotion();
  return (
    <div>
      <div role="radiogroup" aria-label={rotulo} className="-mx-2.5 flex flex-col gap-0.5">
        {opcoes.map((opcao) => {
          const escolhida = opcao.valor === valor;
          return (
            <button
              key={opcao.valor}
              type="button"
              role="radio"
              aria-checked={escolhida}
              onClick={() => aoEscolher(opcao.valor)}
              className={`flex w-full items-start gap-3 rounded-xl px-2.5 py-2 text-left transition-colors ${
                escolhida ? "bg-[var(--ks-brand-50)]" : "hover:bg-[var(--ks-color-bg-hover)]"
              }`}
            >
              <span
                aria-hidden
                className={`mt-0.5 flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-full border-2 transition-colors ${
                  escolhida ? "border-[var(--ks-brand-600)] bg-[var(--ks-brand-600)]" : "border-[var(--ks-color-border-strong)]"
                }`}
              >
                {escolhida ? (
                  <motion.span
                    initial={parado ? false : { scale: 0 }}
                    animate={{ scale: 1 }}
                    transition={{ type: "spring", stiffness: 500, damping: 30 }}
                    className="h-1.5 w-1.5 rounded-full bg-white"
                  />
                ) : null}
              </span>
              <span className="min-w-0">
                <span
                  className={`block text-sm ${
                    escolhida ? "font-bold text-[var(--ks-color-text-primary)]" : "font-semibold text-[var(--ks-color-text-secondary)]"
                  }`}
                >
                  {opcao.titulo}
                </span>
                {opcao.texto ? <span className="block text-xs leading-relaxed text-[var(--ks-color-text-muted)]">{opcao.texto}</span> : null}
              </span>
            </button>
          );
        })}
      </div>
      {ajuda ? <p className="mt-2 text-xs leading-relaxed text-[var(--ks-color-text-soft)]">{ajuda}</p> : null}
    </div>
  );
}

/** Campo de texto longo no traço dos campos da casa. */
export function AreaDeTexto(props: TextareaHTMLAttributes<HTMLTextAreaElement>) {
  const { className = "", ...resto } = props;
  return <textarea {...resto} className={`ks-field min-h-[76px] resize-y ${className}`} />;
}
