"use client";

import { useCallback, useEffect, useRef, useState, type KeyboardEvent, type PointerEvent } from "react";
import { chaveDosVistos, juntarVisto, lerListaDosVistos, posicaoPeloTeclado } from "@/lib/widgets-da-home";

/*
  O comportamento dos blocos novos que os dois desenhos (Padrão/Vitrine e
  Vendor) dividem: vistos recentemente, copiar o cupom, movimento reduzido e
  a barra do antes e depois. Só lógica; cada desenho tem a sua cara.
*/

/* --------------------------------------------- vistos recentemente */

const EVENTO_DOS_VISTOS = "ktalogu:vistos";

/** Guarda o produto aberto na lista do navegador (nada vai para o servidor). */
export function guardarVisto(slug: string, produtoId: string) {
  try {
    const chave = chaveDosVistos(slug);
    const lista = juntarVisto(lerListaDosVistos(window.localStorage.getItem(chave)), produtoId);
    window.localStorage.setItem(chave, JSON.stringify(lista));
    window.dispatchEvent(new Event(EVENTO_DOS_VISTOS));
  } catch {
    /* Navegador sem armazenamento (aba anônima, bloqueio): a lista fica vazia. */
  }
}

/** A lista do navegador (vazia no servidor e na primeira visita). */
export function useVistos(slug: string): string[] {
  const [lista, setLista] = useState<string[]>([]);
  useEffect(() => {
    const ler = () => {
      try {
        setLista(lerListaDosVistos(window.localStorage.getItem(chaveDosVistos(slug))));
      } catch {
        setLista([]);
      }
    };
    const primeiro = window.setTimeout(ler, 0);
    window.addEventListener(EVENTO_DOS_VISTOS, ler);
    window.addEventListener("storage", ler);
    return () => {
      window.clearTimeout(primeiro);
      window.removeEventListener(EVENTO_DOS_VISTOS, ler);
      window.removeEventListener("storage", ler);
    };
  }, [slug]);
  return lista;
}

/* --------------------------------------------------- copiar o cupom */

/** Copia o texto. Sem a área de transferência moderna, tenta o jeito antigo. */
export async function copiarTexto(texto: string): Promise<boolean> {
  try {
    if (navigator.clipboard?.writeText) {
      await navigator.clipboard.writeText(texto);
      return true;
    }
  } catch {
    /* segue para o jeito antigo */
  }
  try {
    const campo = document.createElement("textarea");
    campo.value = texto;
    campo.setAttribute("readonly", "");
    campo.style.position = "fixed";
    campo.style.opacity = "0";
    document.body.appendChild(campo);
    campo.select();
    const ok = document.execCommand("copy");
    document.body.removeChild(campo);
    return ok;
  } catch {
    return false;
  }
}

/** O botão "Copiar": o estado de copiado volta sozinho depois de uns segundos. */
export function useCopiar() {
  const [estado, setEstado] = useState<"parado" | "copiado" | "falhou">("parado");
  const relogio = useRef<number | null>(null);
  useEffect(() => () => {
    if (relogio.current) window.clearTimeout(relogio.current);
  }, []);
  const copiar = useCallback(async (texto: string) => {
    const ok = await copiarTexto(texto);
    setEstado(ok ? "copiado" : "falhou");
    if (relogio.current) window.clearTimeout(relogio.current);
    relogio.current = window.setTimeout(() => setEstado("parado"), 2600);
  }, []);
  return { estado, copiar };
}

/* ------------------------------------------------ movimento reduzido */

export function useMovimentoReduzido() {
  const [reduzido, setReduzido] = useState(false);
  useEffect(() => {
    let consulta: MediaQueryList | null = null;
    try {
      consulta = window.matchMedia("(prefers-reduced-motion: reduce)");
    } catch {
      return;
    }
    const marcar = () => setReduzido(Boolean(consulta?.matches));
    const primeiro = window.setTimeout(marcar, 0);
    consulta.addEventListener?.("change", marcar);
    return () => {
      window.clearTimeout(primeiro);
      consulta?.removeEventListener?.("change", marcar);
    };
  }, []);
  return reduzido;
}

/* ------------------------------------------- a barra do antes e depois */

/**
 * Arrastar com o mouse, o dedo ou a caneta (pointer events, com captura) e
 * mexer pelo teclado (setas, Home, End). A posição é de 0 a 100: quanto da
 * imagem "depois" aparece da esquerda.
 */
export function useBarraDeComparacao(inicio: number) {
  const [posicao, setPosicao] = useState(inicio);
  const caixa = useRef<HTMLDivElement | null>(null);
  const arrastando = useRef(false);

  useEffect(() => {
    const t = window.setTimeout(() => setPosicao(inicio), 0);
    return () => window.clearTimeout(t);
  }, [inicio]);

  const marcarPelo = (x: number) => {
    const area = caixa.current?.getBoundingClientRect();
    if (!area || area.width <= 0) return;
    setPosicao(Math.min(100, Math.max(0, ((x - area.left) / area.width) * 100)));
  };

  const eventosDaCaixa = {
    onPointerDown: (e: PointerEvent<HTMLDivElement>) => {
      arrastando.current = true;
      try {
        e.currentTarget.setPointerCapture(e.pointerId);
      } catch {
        /* navegador antigo: segue sem captura */
      }
      marcarPelo(e.clientX);
    },
    onPointerMove: (e: PointerEvent<HTMLDivElement>) => {
      if (arrastando.current) marcarPelo(e.clientX);
    },
    onPointerUp: () => {
      arrastando.current = false;
    },
    onPointerCancel: () => {
      arrastando.current = false;
    },
  };

  const eventosDaAlca = {
    onKeyDown: (e: KeyboardEvent<HTMLElement>) => {
      const nova = posicaoPeloTeclado(posicao, e.key);
      if (nova === null) return;
      e.preventDefault();
      setPosicao(nova);
    },
  };

  return { posicao, caixa, eventosDaCaixa, eventosDaAlca };
}
