"use client";

import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { Download, LogIn, PlayCircle } from "lucide-react";
import ClientPortalFavoriteButton from "@/components/ClientPortalFavoriteButton";
import { useVisaoDaLoja } from "@/components/VisaoDaLojaContext";
import { trackCatalogEvent } from "@/lib/catalog-analytics";
import { estaEsgotado } from "@/lib/loja/regras-da-loja";
import { moedaDaBoutique } from "./formato";
import { useMemo } from "react";

/*
  O card de produto da Boutique, no desenho da referência: foto 2:3 sobre
  #FAFAFA (a segunda foto entra no hover, com fade), nome em caixa alta,
  preço grande e a linha cinza embaixo. Sem borda e sem sombra — nada de
  "card flutuante". Selos no canto: promoção em vermelho (#FF0000) e
  "Esgotado" em preto, pela mesma regra do Padrão.

  `h-full flex flex-col` no card, `flex-1` no corpo e `mt-auto` no preço: é o
  que alinha os preços da fileira mesmo com nomes de tamanhos diferentes. O
  nome reserva duas linhas.

  Parcelamento ("ou 5x de R$ …") não aparece: a loja não cadastra condição de
  parcelas, e o card não promete o que o checkout não garante. No lugar, a
  linha cinza diz o que o preço quer dizer (a partir de quantas unidades,
  por m², entrega do digital).

  O preço obedece às regras da loja (lib/loja/regras-da-loja.ts): o produto
  chega aqui já sem preço quando o visitante não pode ver, e o card só
  escreve o texto que a loja escolheu no lugar dele. Quando o preço é só
  para quem entrou, esse lugar vira o caminho do login.
*/

/* Para onde o login manda de volta: a página em que o cliente estava. */
function enderecoDoLogin(slug: string, caminho: string | null) {
  return `/${slug}/cliente/login?next=${encodeURIComponent(caminho || `/${slug}`)}`;
}

export type BoutiqueProduto = {
  id: string;
  name: string;
  price: number;
  image_url?: string | null;
  price_on_request?: boolean | null;
  unit_type?: string | null;
  product_images?: Array<{ image_url: string; is_primary?: boolean | null; sort_order?: number | null }> | null;
  product_price_tiers?: Array<{
    min_qty: number;
    max_qty: number | null;
    unit_price: number;
    active?: boolean | null;
  }> | null;
  min_sale_qty_enabled?: boolean | null;
  min_sale_qty?: number | null;
  /* As características (tamanho, cor): a barra do hover mostra as opções. */
  product_attributes?: Array<{
    name?: string | null;
    options?: Array<string | { label?: string | null }> | null;
    show_in_store?: boolean | null;
  }> | null;
  /* Estoque: o selo "Esgotado" usa a mesma regra do resto da loja. */
  stock?: number | null;
  track_inventory?: boolean | null;
  allow_negative_stock?: boolean | null;
  estoque_v2?: boolean | null;
  estoque_v2_limita?: boolean | null;
  estoque_v2_esgotado?: boolean | null;
  /* "digital": selo no card e preço sem "a partir de" (é um preço só). */
  product_kind?: string | null;
  /* O tipo do digital ("curso" leva o selo "Curso"). */
  digital_tipo?: string | null;
  /* "encomenda" e a data da pré-venda: o card não promete "na hora". */
  digital_entrega?: string | null;
  digital_pre_venda?: string | null;
};

/* "Entrega na hora", "Sob encomenda" ou "Pré-venda" (a data passou: na hora). */
function entregaNoCard(produto: BoutiqueProduto): string {
  const preVenda = produto.digital_pre_venda ? new Date(produto.digital_pre_venda).getTime() : NaN;
  if (Number.isFinite(preVenda) && preVenda > Date.now()) return "Pré-venda";
  if (produto.digital_entrega === "encomenda") return "Sob encomenda";
  return "Entrega na hora";
}

/* O selo do produto digital, sobre a foto. */
function SeloDigital({ curso = false }: { curso?: boolean }) {
  return (
    <span
      className="pointer-events-none absolute bottom-2 left-2 z-10 inline-flex items-center gap-1 bg-[#111111] px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.06em] text-white"
      style={{ borderRadius: "var(--bq-radius-selo)" }}
    >
      {curso ? <PlayCircle className="h-2.5 w-2.5" strokeWidth={2.5} /> : <Download className="h-2.5 w-2.5" strokeWidth={2.5} />}
      {curso ? "Vídeo" : "Digital"}
    </span>
  );
}

export function fotoDoProduto(produto: BoutiqueProduto) {
  const imagens = (produto.product_images || []).filter((img) => img?.image_url);
  const principal = imagens.find((img) => img.is_primary) || imagens[0];
  return principal?.image_url || produto.image_url || null;
}

/* O menor preço que a loja pratica: a menor faixa, se houver, ou o preço
   cheio. É o número que fica embaixo de "a partir de". */
export function precoInicial(produto: BoutiqueProduto) {
  const faixas = (produto.product_price_tiers || []).filter(
    (faixa) => faixa && faixa.active !== false && Number(faixa.unit_price) > 0
  );
  if (!faixas.length) return Number(produto.price) || 0;
  return faixas.reduce(
    (menor, faixa) => Math.min(menor, Number(faixa.unit_price)),
    Number.POSITIVE_INFINITY
  );
}

/* A quantidade a que o preço inicial se refere: sai como "/ 1.000 un." */
export function quantidadeDoPrecoInicial(produto: BoutiqueProduto) {
  const faixas = (produto.product_price_tiers || []).filter(
    (faixa) => faixa && faixa.active !== false && Number(faixa.unit_price) > 0
  );
  if (!faixas.length) {
    return produto.min_sale_qty_enabled && Number(produto.min_sale_qty) > 1
      ? Number(produto.min_sale_qty)
      : null;
  }
  const menor = faixas.reduce((a, b) => (Number(a.unit_price) <= Number(b.unit_price) ? a : b));
  return Number(menor.min_qty) > 1 ? Number(menor.min_qty) : null;
}

/* A segunda foto do produto (a da modelo vestindo, em loja de moda): é a que
   aparece no hover, com fade, como na referência. */
export function segundaFotoDoProduto(produto: BoutiqueProduto) {
  const imagens = [...(produto.product_images || [])]
    .filter((img) => img?.image_url)
    .sort((a, b) => Number(a.sort_order ?? 0) - Number(b.sort_order ?? 0));
  const principal = fotoDoProduto(produto);
  return imagens.find((img) => img.image_url !== principal)?.image_url || null;
}

/* Preço de verdade mais baixo para UMA peça: uma faixa que começa em 1
   unidade e custa menos que o preço cheio é, para o cliente, uma promoção —
   o card mostra o cheio riscado e o selo com a porcentagem. */
function promocaoDoProduto(produto: BoutiqueProduto) {
  const cheio = Number(produto.price) || 0;
  if (cheio <= 0) return null;
  const faixas = (produto.product_price_tiers || []).filter(
    (faixa) => faixa && faixa.active !== false && Number(faixa.unit_price) > 0 && Number(faixa.min_qty) <= 1
  );
  if (!faixas.length) return null;
  const menor = Math.min(...faixas.map((faixa) => Number(faixa.unit_price)));
  if (!(menor < cheio)) return null;
  const porcentagem = Math.round((1 - menor / cheio) * 100);
  return porcentagem >= 1 ? { cheio, porcentagem } : null;
}

/* As opções que aparecem na barra do hover (tamanhos, cores): a primeira
   característica visível na loja, com poucas opções. */
function opcoesDoCard(produto: BoutiqueProduto) {
  const atributo = (produto.product_attributes || []).find(
    (a) => a && a.show_in_store !== false && Array.isArray(a.options) && a.options.length > 0 && a.options.length <= 8
  );
  if (!atributo) return [];
  return (atributo.options || [])
    .map((opcao) => (typeof opcao === "string" ? opcao : String(opcao?.label || "")).trim())
    .filter(Boolean)
    .slice(0, 6);
}

export function BoutiqueCardDoProduto({
  produto,
  slug,
  clienteId,
  favoritos,
  corDaMarca,
  proporcao = "2 / 3",
  variante = "vitrine",
}: {
  produto: BoutiqueProduto;
  slug: string;
  /* Quem está logado no portal — sem isso o coração manda para o login. */
  clienteId?: string | null;
  favoritos?: string[] | null;
  corDaMarca?: string;
  /* A foto: 2:3 na grade (TOP SELLERS, listagem) e 4:5 nos carrosséis de
     vitrine, como na referência. */
  proporcao?: "2 / 3" | "4 / 5";
  /* "vitrine": texto à esquerda, sem borda (home). "categoria": o card da
     listagem da referência — borda #EFEFEF, texto centralizado, preço e a
     linha cinza na mesma linha. "relacionado": o da categoria sem a borda
     (carrossel de relacionados da página de produto). */
  variante?: "vitrine" | "categoria" | "relacionado";
}) {
  const router = useRouter();
  const caminho = usePathname();
  const visao = useVisaoDaLoja();
  const foto = fotoDoProduto(produto);
  const segunda = segundaFotoDoProduto(produto);
  const href = `/${slug}/p/${produto.id}`;
  /* O clique no produto conta para os relatórios da loja, igual nos outros
     temas. É por este evento que o lojista sabe o que é olhado e não vendido. */
  const contarClique = () => {
    void trackCatalogEvent({ slug, eventName: "product_click", productId: produto.id });
  };
  const preco = useMemo(() => precoInicial(produto), [produto]);
  const quantidade = useMemo(() => quantidadeDoPrecoInicial(produto), [produto]);
  const promocao = useMemo(() => promocaoDoProduto(produto), [produto]);
  const opcoes = useMemo(() => opcoesDoCard(produto), [produto]);
  const porArea = produto.unit_type === "square_meter";
  /* Sem preço: pelo cadastro ("sob consulta") ou pela regra da loja. Nos dois
     casos o que aparece é o texto da loja, nunca um número. */
  const semPreco = Boolean(produto.price_on_request) || !visao.mostrarPreco;
  const textoSemPreco = visao.textoNoLugarDoPreco;
  /* "Esgotado" com a mesma regra do Padrão (lib/loja/regras-da-loja): com a
     regra "esconder", o produto nem chega aqui. */
  const esgotado = visao.regras.esgotado !== "hide" && estaEsgotado(produto);
  const digital = produto.product_kind === "digital";

  /* A linha cinza debaixo do preço: o que o preço quer dizer. */
  const linhaDoPreco = digital
    ? entregaNoCard(produto)
    : quantidade
      ? `a partir de ${quantidade.toLocaleString("pt-BR")} ${porArea ? "m²" : quantidade === 1 ? "unidade" : "unidades"}`
      : porArea
        ? "preço por m²"
        : null;

  const daCategoria = variante !== "vitrine";

  return (
    <div
      className={`bq-card group relative flex h-full flex-col ${variante === "categoria" ? "border bg-white" : ""}`}
      style={variante === "categoria" ? { borderColor: "#efefef" } : undefined}
      {...(daCategoria ? { "data-bq-card-categoria": "" } : {})}
    >
      <div className="relative">
        <Link
          href={href}
          onClick={contarClique}
          aria-label={produto.name}
          className="bq-card-foto relative block overflow-hidden"
          style={{ aspectRatio: proporcao, backgroundColor: "var(--bq-foto-fundo)" }}
          {...(segunda ? { "data-duas": "" } : {})}
        >
          {foto ? (
            /* eslint-disable-next-line @next/next/no-img-element */
            <img
              src={foto}
              alt={produto.name}
              loading="lazy"
              className={`bq-foto-1 absolute inset-0 h-full w-full object-cover object-center ${esgotado ? "opacity-60" : ""}`}
            />
          ) : (
            <span className="absolute inset-0 flex items-center justify-center text-[11px] uppercase tracking-[0.12em] text-[var(--bq-muted-fg)]">
              Sem imagem
            </span>
          )}
          {segunda ? (
            /* eslint-disable-next-line @next/next/no-img-element */
            <img src={segunda} alt="" aria-hidden="true" loading="lazy" className="bq-foto-2 absolute inset-0 h-full w-full object-cover object-center opacity-0" />
          ) : null}
        </Link>

        {/* Os selos ficam no canto de cima, à esquerda: promoção em vermelho,
            esgotado em preto. */}
        {promocao || esgotado ? (
          <span className="pointer-events-none absolute left-2.5 top-2.5 z-10 flex flex-col items-start gap-1">
            {esgotado ? (
              <span
                className="inline-flex min-w-[51px] items-center justify-center bg-[#111111] px-2 py-px text-[10.5px] uppercase leading-[18px] tracking-[0.04em] text-white sm:text-[12px]"
                style={{ borderRadius: "var(--bq-radius-selo)" }}
              >
                Esgotado
              </span>
            ) : null}
            {promocao && !semPreco ? (
              <span
                className="inline-flex min-w-[51px] items-center justify-center px-2 py-px text-[10.5px] leading-[18px] text-white sm:text-[12px]"
                style={{ borderRadius: "var(--bq-radius-selo)", backgroundColor: "var(--bq-selo)" }}
              >
                -{promocao.porcentagem}%
              </span>
            ) : null}
          </span>
        ) : null}
        {digital ? <SeloDigital curso={produto.digital_tipo === "curso"} /> : null}

        {/* O coração do favorito, sobre a foto e fora do link (o clique não
            vira navegação). O botão já se posiciona no canto de cima. */}
        <ClientPortalFavoriteButton
          productId={produto.id}
          clientId={clienteId || null}
          initialFavorites={favoritos || null}
          primaryColor={corDaMarca || "#111111"}
          onRequireLogin={() => router.push(`/${slug}/cliente/login`)}
        />

        {/* A barra do hover (só no computador): as opções do produto, ou o
            caminho para ele na cor do botão do card. */}
        <div className="bq-card-barra pointer-events-none absolute inset-x-2 bottom-2 z-10 hidden lg:block">
          {opcoes.length ? (
            <Link
              href={href}
              onClick={contarClique}
              tabIndex={-1}
              className="pointer-events-auto flex flex-wrap items-center justify-center gap-1.5 px-2 py-2"
              style={{ backgroundColor: "rgba(255,255,255,0.93)", backdropFilter: "blur(8px)", WebkitBackdropFilter: "blur(8px)" }}
            >
              {opcoes.map((opcao) => (
                <span
                  key={opcao}
                  className="inline-flex h-[30px] min-w-[34px] items-center justify-center border bg-white px-2 text-[11px] text-[#252525]"
                  style={{ borderColor: "#ccd1d7", borderRadius: "var(--bq-radius-md)" }}
                >
                  {opcao}
                </span>
              ))}
            </Link>
          ) : (
            <Link
              href={href}
              onClick={contarClique}
              tabIndex={-1}
              className="pointer-events-auto flex h-10 items-center justify-center text-[11px] font-semibold uppercase tracking-[0.12em]"
              style={{ backgroundColor: "var(--bq-card-button, #111111)", color: "#ffffff" }}
            >
              Ver produto
            </Link>
          )}
        </div>
      </div>

      {daCategoria ? (
        /* O card da listagem da referência: tudo centralizado, nome em caixa
           alta com espaçamento largo, preço e a linha cinza lado a lado (no
           celular a linha desce). A promoção fecha o card: o cheio riscado e
           o "(N% OFF)" em vermelho. */
        <div className="flex flex-1 flex-col items-center px-2 pb-4 text-center sm:px-3 sm:pb-5">
          <Link
            href={href}
            onClick={contarClique}
            className="mb-[10px] mt-[15px] line-clamp-2 min-h-[38px] text-[11.5px] uppercase leading-[19px] tracking-[1px] text-black min-[391px]:text-[13px]"
          >
            {produto.name}
          </Link>
          <div className="mt-auto w-full">
            {semPreco ? (
              visao.precisaEntrar ? (
                <Link
                  href={enderecoDoLogin(slug, caminho)}
                  className="inline-flex items-center justify-center gap-1.5 text-[13px] font-semibold leading-snug text-black underline-offset-2 hover:underline"
                >
                  <LogIn className="h-4 w-4 shrink-0" strokeWidth={1.6} />
                  {textoSemPreco}
                </Link>
              ) : (
                <p className="text-[13px] font-semibold leading-snug text-black sm:text-[15px]">{textoSemPreco}</p>
              )
            ) : (
              <>
                <p className="flex flex-col items-center justify-center gap-x-1.5 sm:flex-row sm:flex-wrap sm:items-baseline">
                  <span className="text-[12.25px] font-semibold tabular-nums text-black sm:text-[17px]">
                    {digital && preco <= 0 ? "Grátis" : moedaDaBoutique(preco)}
                  </span>
                  {linhaDoPreco ? (
                    <span className="text-[12px] leading-[1.4] text-[#999999] sm:text-[13.8px]">{linhaDoPreco}</span>
                  ) : null}
                </p>
                {promocao ? (
                  <p className="mt-0.5 flex flex-wrap items-baseline justify-center gap-x-1.5 text-[12px] sm:text-[15px]">
                    <span className="tabular-nums line-through" style={{ color: "#808b99" }}>
                      {moedaDaBoutique(promocao.cheio)}
                    </span>
                    <span style={{ color: "#d7271d" }}>({promocao.porcentagem}% OFF)</span>
                  </p>
                ) : null}
              </>
            )}
          </div>
        </div>
      ) : (
      <div className="flex flex-1 flex-col px-1 pb-3 pt-[10px] sm:px-[10px] sm:pt-[14px]">
        <Link
          href={href}
          onClick={contarClique}
          className="line-clamp-2 min-h-[30px] text-[10.5px] font-normal uppercase leading-[1.45] tracking-[0.01em] text-[var(--bq-nome)] sm:min-h-[35px] sm:text-[12px]"
        >
          {produto.name}
        </Link>

        <div className="mt-auto pt-3 sm:pt-4">
          {semPreco ? (
            visao.precisaEntrar ? (
              /* Preço só para quem entrou: o lugar do preço leva ao login e
                 traz a pessoa de volta para esta página. */
              <Link
                href={enderecoDoLogin(slug, caminho)}
                className="inline-flex items-center gap-1.5 text-[13px] font-semibold leading-snug text-[var(--bq-tinta)] underline-offset-2 hover:underline sm:text-[14px]"
              >
                <LogIn className="h-4 w-4 shrink-0" strokeWidth={1.6} />
                {textoSemPreco}
              </Link>
            ) : (
              <p className="text-[13px] font-semibold leading-snug text-[var(--bq-tinta)] sm:text-[14px]">{textoSemPreco}</p>
            )
          ) : (
            <>
              <p className="flex flex-wrap items-baseline gap-x-1.5">
                <span className="text-[14px] font-semibold leading-[1.25] tracking-[-0.01em] tabular-nums text-[var(--bq-tinta)] min-[391px]:text-[15px] sm:text-[18px]">
                  {digital && preco <= 0 ? "Grátis" : moedaDaBoutique(preco)}
                </span>
                {promocao ? (
                  <span className="text-[8px] tabular-nums line-through sm:text-[10px]" style={{ color: "var(--bq-riscado)" }}>
                    {moedaDaBoutique(promocao.cheio)}
                  </span>
                ) : null}
              </p>
              {linhaDoPreco ? (
                <p className="mt-0.5 text-[13px] leading-[1.35] min-[391px]:text-[14px] sm:text-[16px]" style={{ color: "var(--bq-parcela)" }}>
                  {linhaDoPreco}
                </p>
              ) : null}
            </>
          )}
        </div>
      </div>
      )}
    </div>
  );
}

/* A variante compacta, usada pelas páginas do digital ("Você também pode
   gostar"): é o card da listagem sem a borda, com o texto centralizado — o
   mesmo dos relacionados da página de produto, para as sugestões terem uma
   cara só em todo o template. */
export function BoutiqueCardCompacto({
  produto,
  slug,
  clienteId,
  favoritos,
  corDaMarca,
}: {
  produto: BoutiqueProduto;
  slug: string;
  clienteId?: string | null;
  favoritos?: string[] | null;
  corDaMarca?: string;
}) {
  return (
    <BoutiqueCardDoProduto
      produto={produto}
      slug={slug}
      clienteId={clienteId}
      favoritos={favoritos}
      corDaMarca={corDaMarca}
      variante="relacionado"
    />
  );
}
