"use client";

import { useState } from "react";
import Image from "next/image";
import { Check, Loader2, Minus, Plus, Tag } from "lucide-react";
import { toast } from "sonner";
import ComboConfigModal from "@/components/ComboConfigModal";
import type { ProductCombo, SelectedComboData } from "@/components/ProductCombosWidget";
import { useVisaoDaLoja } from "@/components/VisaoDaLojaContext";
import { moedaDoVendor } from "./formato";

/*
  "Compre junto": os produtos que a loja sugere levar com este.

  O desenho é do Vendor. A conta do desconto, a decisão de abrir a janela de
  configuração e o formato do que sai para o carrinho são os mesmos do resto
  do sistema — um combo montado de outro jeito viraria um pedido que o admin
  não sabe ler.

  Produto sugerido simples entra com um toque. Produto com variação, medida,
  faixa de preço ou regra de quantidade abre a janela de configuração: sem
  ela, o preço mostrado aqui seria um chute.

  Quando a regra da loja esconde o preço deste visitante, o combo chega com
  `preco_oculto`: a sugestão fica, o valor não, e o item pode entrar na lista
  do mesmo jeito — a loja precifica depois.
*/

/* O que o servidor devolve do produto sugerido, na parte que decide se a
   janela de configuração precisa abrir. */
type ProdutoSugerido = {
  unit_type?: string | null;
  product_attributes?: unknown[] | null;
  product_price_tiers?: unknown[] | null;
  min_sale_qty_enabled?: boolean | null;
  max_sale_qty_enabled?: boolean | null;
  allowed_sale_qty_enabled?: boolean | null;
};

export function VendorCompreJunto({
  combos,
  slug,
  corDaMarca,
  aoEscolher,
}: {
  combos: ProductCombo[];
  /* A loja, para o servidor entregar o produto sugerido como este visitante pode vê-lo. */
  slug: string;
  corDaMarca: string;
  aoEscolher: (escolhidos: SelectedComboData[]) => void;
}) {
  const visao = useVisaoDaLoja();
  const [escolhidos, setEscolhidos] = useState<Record<string, SelectedComboData>>({});
  const [carregando, setCarregando] = useState<string | null>(null);
  const [janelaAberta, setJanelaAberta] = useState(false);
  const [comboEmConfiguracao, setComboEmConfiguracao] = useState<ProductCombo | null>(null);
  const [dadosDoCombo, setDadosDoCombo] = useState<Record<string, unknown> | null>(null);

  if (!combos?.length) return null;

  /* Nenhum valor para mostrar: "economize" seria promessa sem número. */
  const todosSemPreco = combos.every((combo) => combo.preco_oculto);

  const precoComDesconto = (combo: ProductCombo) => {
    const cheio = Number(combo.combo_product.price) || 0;
    if (combo.discount_type === "percentage") return cheio - (cheio * Number(combo.discount_value || 0)) / 100;
    if (combo.discount_type === "fixed") return Math.max(0, cheio - Number(combo.discount_value || 0));
    return cheio;
  };

  const publicar = (mapa: Record<string, SelectedComboData>) => {
    setEscolhidos(mapa);
    aoEscolher(Object.values(mapa));
  };

  async function alternar(combo: ProductCombo) {
    /* Sob consulta pelo cadastro, com preço visível: não há valor para somar
       ao pedido. Com o preço escondido pela regra da loja o item entra, e a
       loja põe o valor no orçamento. */
    if (combo.combo_product.price_on_request && !combo.preco_oculto) {
      toast.error("O produto sugerido está sob consulta e não pode ser adicionado direto.");
      return;
    }

    if (escolhidos[combo.id]) {
      const mapa = { ...escolhidos };
      delete mapa[combo.id];
      publicar(mapa);
      return;
    }

    setCarregando(combo.id);
    try {
      /* Pelo servidor, que entrega só o que a vitrine usa e só o que este
         visitante pode ver. Antes o navegador consultava o banco direto com a
         chave pública, e levava junto custo e preço que a regra esconde. */
      const resposta = await fetch(
        `/api/catalog/produto?slug=${encodeURIComponent(slug)}&id=${encodeURIComponent(combo.combo_product.id)}`
      );
      const corpo = (await resposta.json().catch(() => null)) as
        | { produto?: Record<string, unknown> | null; error?: string }
        | null;
      const data = (corpo?.produto || null) as (Record<string, unknown> & ProdutoSugerido) | null;
      if (!resposta.ok || !data) throw new Error(corpo?.error || "Produto não encontrado");

      const temVariacao = Array.isArray(data.product_attributes) && data.product_attributes.length > 0;
      const porMedida = data.unit_type === "square_meter" || data.unit_type === "linear_meter";
      const temFaixas = Array.isArray(data.product_price_tiers) && data.product_price_tiers.length > 0;
      const temRegraDeQuantidade =
        data.min_sale_qty_enabled || data.max_sale_qty_enabled || data.allowed_sale_qty_enabled;

      if (temVariacao || porMedida || temFaixas || temRegraDeQuantidade) {
        setDadosDoCombo(data);
        setComboEmConfiguracao(combo);
        setJanelaAberta(true);
        return;
      }

      publicar({
        ...escolhidos,
        [combo.id]: {
          combo,
          quantity: 1,
          discountedPrice: precoComDesconto(combo),
          configuration: { unit_type: data.unit_type ?? undefined },
        },
      });
    } catch {
      toast.error("Não foi possível carregar os detalhes deste produto.");
    } finally {
      setCarregando(null);
    }
  }

  function mudarQuantidade(combo: ProductCombo, nova: number) {
    const atual = escolhidos[combo.id];
    if (!atual) return;
    publicar({ ...escolhidos, [combo.id]: { ...atual, quantity: Math.max(1, nova) } });
  }

  return (
    <section className="space-y-2">
      <h3 className="flex items-center gap-2 text-sm font-semibold">
        <Tag className="h-4 w-4" style={{ color: corDaMarca }} />
        {todosSemPreco ? "Compre junto" : "Compre junto e economize"}
      </h3>

      <div className="space-y-2">
        {combos.map((combo) => {
          const escolhido = escolhidos[combo.id];
          const cheio = Number(combo.combo_product.price) || 0;
          const comDesconto = escolhido?.discountedPrice ?? precoComDesconto(combo);
          const temDesconto = combo.discount_type !== "none" && comDesconto < cheio;
          /* Escondido pela loja: nem preço nem "sob consulta", só o produto. */
          const precoEscondido = Boolean(combo.preco_oculto);
          const sobConsulta = combo.combo_product.price_on_request;

          return (
            <div
              key={combo.id}
              className="flex items-center gap-3 border p-2.5 transition-colors"
              style={{
                borderRadius: "var(--vd-radius-lg)",
                borderColor: escolhido ? corDaMarca : "var(--vd-border)",
                backgroundColor: escolhido ? "color-mix(in srgb, var(--vd-primary) 6%, transparent)" : undefined,
              }}
            >
              <button
                type="button"
                onClick={() => alternar(combo)}
                disabled={carregando === combo.id}
                aria-label={escolhido ? "Remover do pedido" : "Adicionar ao pedido"}
                className="flex h-6 w-6 shrink-0 items-center justify-center border transition-colors disabled:opacity-50"
                style={{
                  borderRadius: "var(--vd-radius-sm)",
                  borderColor: escolhido ? corDaMarca : "var(--vd-border)",
                  backgroundColor: escolhido ? corDaMarca : "transparent",
                  color: escolhido ? "var(--vd-primary-fg)" : "var(--vd-muted-fg)",
                }}
              >
                {carregando === combo.id ? (
                  <Loader2 className="h-3.5 w-3.5 animate-spin" />
                ) : escolhido ? (
                  <Check className="h-3.5 w-3.5" />
                ) : (
                  <Plus className="h-3.5 w-3.5" />
                )}
              </button>

              <span
                className="relative h-12 w-12 shrink-0 overflow-hidden border"
                style={{ borderRadius: "var(--vd-radius-md)", borderColor: "var(--vd-border)" }}
              >
                {combo.combo_product.image_url ? (
                  <Image
                    src={combo.combo_product.image_url}
                    alt={combo.combo_product.name}
                    fill
                    sizes="48px"
                    className="object-cover"
                    unoptimized
                  />
                ) : null}
              </span>

              <div className="min-w-0 flex-1">
                <p className="truncate text-[13px] font-medium leading-snug">{combo.combo_product.name}</p>
                {precoEscondido ? null : (
                  <p className="mt-0.5 flex items-center gap-1.5 text-[12.5px]">
                    {sobConsulta ? (
                      <span className="text-[var(--vd-muted-fg)]">{visao.textoNoLugarDoPreco}</span>
                    ) : (
                      <>
                        {temDesconto ? (
                          <span className="text-[11.5px] text-[var(--vd-muted-fg)] line-through">
                            {moedaDoVendor(cheio)}
                          </span>
                        ) : null}
                        <span className="font-bold tabular-nums" style={{ color: corDaMarca }}>
                          {moedaDoVendor(comDesconto)}
                        </span>
                      </>
                    )}
                  </p>
                )}
              </div>

              {escolhido ? (
                <div
                  className="inline-flex shrink-0 items-center border"
                  style={{ borderRadius: "var(--vd-radius-md)", borderColor: "var(--vd-border)" }}
                >
                  <button
                    type="button"
                    aria-label="Diminuir"
                    onClick={() => mudarQuantidade(combo, escolhido.quantity - 1)}
                    className="inline-flex h-8 w-8 items-center justify-center transition-colors hover:bg-[var(--vd-muted-bg)]"
                  >
                    <Minus className="h-3.5 w-3.5" />
                  </button>
                  <span className="w-7 text-center text-[13px] font-semibold tabular-nums">{escolhido.quantity}</span>
                  <button
                    type="button"
                    aria-label="Aumentar"
                    onClick={() => mudarQuantidade(combo, escolhido.quantity + 1)}
                    className="inline-flex h-8 w-8 items-center justify-center transition-colors hover:bg-[var(--vd-muted-bg)]"
                  >
                    <Plus className="h-3.5 w-3.5" />
                  </button>
                </div>
              ) : null}
            </div>
          );
        })}
      </div>

      {/* A janela de configuração é a mesma do resto do sistema: ela resolve
          variação, medida e faixa do produto sugerido, e devolve o preço já
          calculado. Ter uma cópia própria seria manter duas contas. */}
      <ComboConfigModal
        isOpen={janelaAberta}
        onClose={() => setJanelaAberta(false)}
        combo={comboEmConfiguracao}
        productData={dadosDoCombo}
        primaryColor={corDaMarca}
        onConfirm={(quantidade, configuracao) => {
          if (!comboEmConfiguracao) return;
          const preco =
            (configuracao as { resolvedUnitPrice?: number } | null)?.resolvedUnitPrice ??
            precoComDesconto(comboEmConfiguracao);
          publicar({
            ...escolhidos,
            [comboEmConfiguracao.id]: {
              combo: comboEmConfiguracao,
              quantity: quantidade,
              discountedPrice: preco,
              configuration: configuracao,
            },
          });
          setJanelaAberta(false);
        }}
      />

    </section>
  );
}
