"use client";

import Image from "next/image";
import { Check, Package, ShoppingBag, Trash2 } from "lucide-react";
import { CustomSelect } from "@/components/ui/custom-select";
import { quantidadeDoItem, resumoDaMedida } from "@/lib/orders/quantidade-do-item";
import { formatMeasureInput, formatMoney, formatMoneyInput, parseMeasureInput, parseMoneyInput } from "@/utils/formatters";
import { textoDoMinimoAplicado } from "@/lib/adicionais";
import {
  getItemVariationMap,
  getProductAllowedQuantities,
  getSelectedOptionsSummary,
  getSortedAttributes,
  normalizeAttributeOption,
  resolveItemUnitPrice,
  totalDaLinha,
  minimoDaLinhaDoPdv,
  minimoDoProdutoNoPdv,
  type CartItem,
  type ProductAttributeValue,
  type ProductRow,
} from "@/lib/pdv/carrinho";

/*
  O cupom: o que está sendo vendido, linha a linha.

  Cada linha mostra o essencial — foto, nome, preço unitário, total. Clicar
  abre a linha para mexer no que muda de venda para venda: quantidade, medida,
  preço, observação e variações. O que não está aberto não ocupa espaço.
*/

const passthroughLoader = ({ src }: { src: string }) => src;

type Rascunhos = Record<string, { width_m: string; height_m: string }>;

export function Cupom({
  cart,
  products,
  productImageById,
  activeItemId,
  setActiveItemId,
  justAddedCartItemId,
  measureDrafts,
  setMeasureDrafts,
  updateItem,
  removeItem,
  changeQuantity,
  updateItemVariationSelection,
  subtotal,
  discountInput,
  setDiscountInput,
  total,
  aoReceber,
  podeFecharVenda,
  aviso,
  pixPago,
  faltasDeEstoque,
}: {
  cart: CartItem[];
  products: ProductRow[];
  productImageById: Map<string, string>;
  activeItemId: string | null;
  setActiveItemId: (atualizar: (antes: string | null) => string | null) => void;
  justAddedCartItemId: string | null;
  measureDrafts: Rascunhos;
  setMeasureDrafts: (atualizar: (antes: Rascunhos) => Rascunhos) => void;
  updateItem: (itemId: string, patch: Partial<CartItem>) => void;
  removeItem: (itemId: string) => void;
  changeQuantity: (itemId: string, delta: number) => void;
  updateItemVariationSelection: (itemId: string, product: ProductRow, attribute: ProductAttributeValue, optionLabel: string) => void;
  subtotal: number;
  discountInput: string;
  setDiscountInput: (valor: string) => void;
  total: number;
  aoReceber: () => void;
  podeFecharVenda: boolean;
  aviso: string | null;
  /* Um Pix já pago pelo Mercado Pago, preso a esta venda: lembra e cobra. */
  pixPago: { valor: number; aprovadaEm: string | null } | null;
  /* A falta de estoque de cada linha (id do item → frases), conferida no
     banco pela mesma conta da loja e do orçamento. */
  faltasDeEstoque?: Map<string, string[]>;
}) {
  const totalDePecas = cart.reduce((soma, item) => soma + Math.max(1, item.quantity || 1), 0);

  return (
    <aside className="pdv-folha">
      <div className="pdv-cupom-topo">
        <span className="pdv-eyebrow">Cupom</span>
        <span className="text-[12px] font-semibold text-[var(--ks-color-text-soft)]">
          {cart.length === 0 ? "vazio" : `${totalDePecas} ${totalDePecas === 1 ? "peça" : "peças"}`}
        </span>
      </div>

      <div className="pdv-cupom-lista">
        {cart.length === 0 ? (
          <div className="pdv-cupom-vazio">
            <ShoppingBag size={26} />
            <strong>Nada no cupom ainda</strong>
            <span>Clique num produto ou leia o código de barras.</span>
          </div>
        ) : (
          cart.map((item) => {
            const porMetro = item.unit_type === "square_meter";
            const linha = totalDaLinha(item);
            const minimoDaLinha = minimoDaLinhaDoPdv(item);
            const ativa = activeItemId === item.id;
            const foto = item.product_id ? productImageById.get(item.product_id) || "" : "";
            const produto = item.product_id ? products.find((entrada) => entrada.id === item.product_id) || null : null;
            const permitidas = getProductAllowedQuantities(produto);
            const usaPermitidas = Boolean(produto?.allowed_sale_qty_enabled) && permitidas.length > 0;
            const permitidaAtual = usaPermitidas ? permitidas.find((valor) => Math.abs(valor - item.quantity) <= 0.000001) : null;
            const rascunho = measureDrafts[item.id];
            const atributos = produto ? getSortedAttributes(produto).filter((atributo) => (atributo.options || []).length > 0) : [];
            const escolhidas = getItemVariationMap(item.selected_options);

            return (
              <div
                key={item.id}
                className={`pdv-linha ${ativa ? "pdv-linha-ativa" : ""} ${justAddedCartItemId === item.id ? "pdv-linha-nova" : ""}`}
              >
                <button
                  type="button"
                  className="pdv-linha-cabeca"
                  onClick={() => setActiveItemId((antes) => (antes === item.id ? null : item.id))}
                >
                  <div className="pdv-linha-foto">
                    {foto ? (
                      <Image src={foto} alt={item.title} width={40} height={40} sizes="40px" loader={passthroughLoader} unoptimized />
                    ) : (
                      <Package size={16} />
                    )}
                  </div>
                  <div className="min-w-0">
                    <div className="pdv-linha-nome">{item.title}</div>
                    <div className="pdv-linha-sub">
                      {minimoDaLinha
                        ? `${porMetro ? resumoDaMedida(item) : item.quantity} · Valor mínimo`
                        : porMetro
                          ? `${resumoDaMedida(item)} · ${formatMoney(item.unit_price)}/m²`
                          : `${item.quantity} × ${formatMoney(item.unit_price)}`}
                      {item.selected_options ? ` · ${getSelectedOptionsSummary(item.selected_options)}` : ""}
                      {item.note ? ` · ${item.note}` : ""}
                    </div>
                    {minimoDaLinha ? (
                      <div className="pdv-linha-sub" style={{ color: "#0369a1" }}>
                        {textoDoMinimoAplicado(minimoDaLinha.minimo, minimoDaLinha.semMinimo)}
                      </div>
                    ) : null}
                    {(faltasDeEstoque?.get(item.id) || []).map((frase) => (
                      <div key={frase} className="pdv-linha-sub" style={{ color: "#be123c", fontWeight: 600, whiteSpace: "normal", overflow: "visible" }}>
                        {frase}
                      </div>
                    ))}
                  </div>
                  <div className="pdv-linha-total">{formatMoney(linha)}</div>
                </button>

                <div className="pdv-linha-acoes">
                  {porMetro ? (
                    <>
                      <div className="pdv-passo" title="Quantas peças com esta medida">
                        <button type="button" onClick={() => updateItem(item.id, { quantity: Math.max(1, (item.quantity || 1) - 1) })} aria-label="Uma peça a menos">
                          −
                        </button>
                        <span>{item.quantity || 1}</span>
                        <button type="button" onClick={() => updateItem(item.id, { quantity: (item.quantity || 1) + 1 })} aria-label="Uma peça a mais">
                          +
                        </button>
                      </div>
                      <div className="pdv-medida">
                        <input
                          type="text"
                          inputMode="decimal"
                          className="pdv-campo"
                          value={rascunho?.width_m ?? formatMeasureInput(item.width_m ?? 1)}
                          onFocus={() =>
                            setMeasureDrafts((antes) => ({
                              ...antes,
                              [item.id]: {
                                width_m: antes[item.id]?.width_m ?? formatMeasureInput(item.width_m ?? 1),
                                height_m: antes[item.id]?.height_m ?? formatMeasureInput(item.height_m ?? 1),
                              },
                            }))
                          }
                          onChange={(evento) => {
                            const proximo = formatMeasureInput(evento.target.value);
                            setMeasureDrafts((antes) => ({
                              ...antes,
                              [item.id]: { width_m: proximo, height_m: antes[item.id]?.height_m ?? formatMeasureInput(item.height_m ?? 1) },
                            }));
                            updateItem(item.id, { width_m: parseMeasureInput(proximo) });
                          }}
                          placeholder="0,000"
                        />
                        <span>m ×</span>
                        <input
                          type="text"
                          inputMode="decimal"
                          className="pdv-campo"
                          value={rascunho?.height_m ?? formatMeasureInput(item.height_m ?? 1)}
                          onFocus={() =>
                            setMeasureDrafts((antes) => ({
                              ...antes,
                              [item.id]: {
                                width_m: antes[item.id]?.width_m ?? formatMeasureInput(item.width_m ?? 1),
                                height_m: antes[item.id]?.height_m ?? formatMeasureInput(item.height_m ?? 1),
                              },
                            }))
                          }
                          onChange={(evento) => {
                            const proximo = formatMeasureInput(evento.target.value);
                            setMeasureDrafts((antes) => ({
                              ...antes,
                              [item.id]: { width_m: antes[item.id]?.width_m ?? formatMeasureInput(item.width_m ?? 1), height_m: proximo },
                            }));
                            updateItem(item.id, { height_m: parseMeasureInput(proximo) });
                          }}
                          placeholder="0,000"
                        />
                        <span>m</span>
                      </div>
                      <span className="pdv-selo">
                        {new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 3 }).format(quantidadeDoItem(item).totalNumero ?? 0)} m²
                      </span>
                    </>
                  ) : usaPermitidas ? (
                    <div className="w-[118px]">
                      <CustomSelect
                        options={permitidas.map((valor) => ({ value: String(valor), label: String(valor).replace(".", ",") }))}
                        value={String(permitidaAtual ?? permitidas[0])}
                        onChange={(valor) => {
                          const numero = Number(valor);
                          if (!Number.isFinite(numero) || numero <= 0 || !produto) return;
                          updateItem(item.id, {
                            quantity: numero,
                            unit_price: resolveItemUnitPrice(produto, item.selected_options, numero),
                            valor_minimo_item: minimoDoProdutoNoPdv(produto),
                          });
                        }}
                        portal={false}
                        className="pdv-select-compacto"
                      />
                    </div>
                  ) : (
                    <div className="pdv-passo">
                      <button type="button" onClick={() => changeQuantity(item.id, -1)} aria-label="Menos um">
                        −
                      </button>
                      <span>{item.quantity}</span>
                      <button type="button" onClick={() => changeQuantity(item.id, 1)} aria-label="Mais um">
                        +
                      </button>
                    </div>
                  )}
                  <button type="button" className="pdv-lixeira" onClick={() => removeItem(item.id)} aria-label="Tirar do cupom">
                    <Trash2 size={14} />
                  </button>
                </div>

                {ativa ? (
                  <div className="pdv-linha-editar">
                    <div className="grid grid-cols-[120px_minmax(0,1fr)] gap-2">
                      <div>
                        <label className="pdv-rotulo">Preço {porMetro ? "do m²" : "unitário"}</label>
                        <input
                          value={formatMoneyInput(String(Math.round(item.unit_price * 100)))}
                          onChange={(evento) =>
                            /* Preço digitado à mão: a linha sai do valor mínimo do item. */
                            updateItem(item.id, { unit_price: parseMoneyInput(evento.target.value), valor_minimo_item: null })
                          }
                          className="pdv-campo pdv-campo-num"
                          placeholder="0,00"
                        />
                      </div>
                      <div>
                        <label className="pdv-rotulo">Observação</label>
                        <input
                          value={item.note}
                          onChange={(evento) => updateItem(item.id, { note: evento.target.value })}
                          className="pdv-campo"
                          placeholder="Vai no cupom e no pedido"
                        />
                      </div>
                    </div>
                    {produto && atributos.length > 0 ? (
                      <div className="pdv-variacoes">
                        {atributos.map((atributo) => {
                          const opcoes = (atributo.options || [])
                            .map((opcao, indice) => normalizeAttributeOption(opcao, indice))
                            .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
                          const marcadas = escolhidas[atributo.name] || [];
                          return (
                            <div key={`${item.id}-${atributo.name}`}>
                              <div className="pdv-variacao-nome">{atributo.name}</div>
                              <div className="pdv-opcoes mt-1">
                                {opcoes.map((opcao) => {
                                  const marcada = marcadas.includes(opcao.label);
                                  return (
                                    <button
                                      key={`${item.id}-${atributo.name}-${opcao.id || opcao.label}`}
                                      type="button"
                                      className={`pdv-opcao ${marcada ? "pdv-opcao-ativa" : ""}`}
                                      onClick={() => updateItemVariationSelection(item.id, produto, atributo, opcao.label)}
                                    >
                                      {opcao.label}
                                      {(Number(opcao.price) || 0) > 0 ? ` +${formatMoney(Number(opcao.price) || 0)}` : ""}
                                    </button>
                                  );
                                })}
                              </div>
                            </div>
                          );
                        })}
                      </div>
                    ) : null}
                  </div>
                ) : null}
              </div>
            );
          })
        )}
      </div>

      <div className="pdv-totais">
        <div className="pdv-total-linha">
          <span>Subtotal</span>
          <span>{formatMoney(subtotal)}</span>
        </div>
        <div className="pdv-total-linha">
          <span>Desconto</span>
          <input
            value={discountInput}
            onChange={(evento) => setDiscountInput(formatMoneyInput(evento.target.value))}
            placeholder="0,00"
            className="pdv-campo pdv-campo-num"
            aria-label="Desconto"
          />
        </div>
        <div className="pdv-total-grande">
          <span className="pdv-eyebrow">Total</span>
          <strong>{formatMoney(total)}</strong>
        </div>
        {aviso ? <div className="pdv-aviso pdv-aviso-erro">{aviso}</div> : null}
        {pixPago ? (
          <div className="pdv-chip-pix">
            <Check size={14} />
            Pix de {formatMoney(pixPago.valor)} já pago
            <span>
              {pixPago.aprovadaEm
                ? `às ${new Date(pixPago.aprovadaEm).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })} · `
                : ""}
              preso a esta venda
            </span>
          </div>
        ) : null}
        <button type="button" className="pdv-receber" disabled={cart.length === 0 || !podeFecharVenda} onClick={aoReceber}>
          {pixPago ? "Concluir venda" : "Receber"}
          <kbd>F9</kbd>
        </button>
        {!podeFecharVenda ? (
          <p className="text-center text-[11px] text-[var(--ks-color-text-soft)]">
            Você pode consultar o PDV, mas fechar a venda depende de criar pedidos e lançar no financeiro.
          </p>
        ) : null}
      </div>
    </aside>
  );
}
