"use client";

import { AnimatePresence, motion } from "framer-motion";
import {
  BarChart3,
  Check,
  AlertCircle,
  Copy,
  DollarSign,
  Eye,
  EyeOff,
  FileDown,
  Package,
  Pencil,
  Plus,
  Send,
  Sparkles,
  TrendingUp,
  Trash2,
  X,
  MessageSquare,
  ChevronDown,
  ChevronRight,
  Calendar,
  ExternalLink,
  Save,
  Settings,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";
import { useEffect, useMemo, useState, useRef } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
import { PageHeader } from "@/components/ui/page-header";
import { RevenueChart } from "@/components/dashboard/revenue-chart";
import { Button } from "@/components/ui/button";
import { usePermissoes } from "@/lib/permissoes-do-usuario";
import { Input } from "@/components/ui/input";
import { CustomSelect } from "@/components/ui/custom-select";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { getSupabaseClient } from "@/lib/supabase";
import { getCompanyContext, shouldUseEmployeeUi } from "@/lib/company-context";
import { fetchWhatsAppTemplates, resolveTemplate } from "@/lib/whatsapp-templates-client";
import { normalizarCondicoes, resumirCondicoes } from "@/lib/condicoes-comerciais";
import { resolveTierPrice, type ProductPriceTier } from "@/lib/price-tiers";
import { valorMinimoDoItem, textoDoMinimoAplicado, COLUNAS_DO_VALOR_MINIMO } from "@/lib/adicionais";
import { formatMeasureInput, formatMoneyInput, parseMeasureInput, parseMoneyInput } from "@/utils/formatters";
import { registrarEnvioDoLink } from "@/lib/envio-do-link";
import { prazoDoLink } from "@/lib/prazo-do-link";

function WhatsAppIcon({ className = "" }: { className?: string }) {
  return (
    <svg viewBox="0 0 24 24" aria-hidden="true" className={className} fill="currentColor">
      <path d="M19.05 4.91A9.82 9.82 0 0 0 12.03 2C6.62 2 2.23 6.39 2.23 11.8c0 1.73.45 3.42 1.31 4.91L2.15 22l5.43-1.35a9.75 9.75 0 0 0 4.45 1.13h.01c5.4 0 9.79-4.39 9.8-9.8a9.72 9.72 0 0 0-2.79-7.07Zm-7.02 15.2h-.01a8.1 8.1 0 0 1-4.12-1.13l-.29-.17-3.22.8.86-3.14-.19-.32a8.1 8.1 0 0 1-1.24-4.34c0-4.48 3.64-8.13 8.13-8.13 2.17 0 4.22.85 5.75 2.39a8.07 8.07 0 0 1 2.38 5.75c0 4.48-3.65 8.13-8.05 8.13Zm4.46-6.08c-.24-.12-1.43-.7-1.66-.78-.22-.08-.39-.12-.55.12-.16.24-.63.78-.77.94-.14.16-.28.18-.52.06-.24-.12-1-.37-1.91-1.18-.7-.63-1.18-1.4-1.32-1.64-.14-.24-.01-.37.11-.49.11-.11.24-.28.37-.42.12-.14.16-.24.24-.4.08-.16.04-.3-.02-.42-.06-.12-.55-1.33-.76-1.82-.2-.48-.4-.41-.55-.42h-.47c-.16 0-.42.06-.64.3-.22.24-.84.82-.84 2s.86 2.32.98 2.48c.12.16 1.68 2.56 4.07 3.59.57.25 1.02.4 1.37.52.58.18 1.1.16 1.52.1.46-.07 1.43-.58 1.63-1.14.2-.56.2-1.04.14-1.14-.05-.1-.21-.16-.45-.28Z" />
    </svg>
  );
}

// Stats serão gerados dinamicamente com dados reais

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

const item = {
  hidden: { y: 20, opacity: 0 },
  show: { y: 0, opacity: 1 },
};

type QuoteStatus = "draft" | "sent" | "approved" | "rejected" | "production" | "delivered";

type StatVariant = "primary" | "light";

type StatCard = {
  title: string;
  rawValue: number;
  format: "currency" | "number";
  change: string;
  icon: LucideIcon;
  description: string;
  variant: StatVariant;
  sensitive?: boolean;
};

type RecentActivity = {
  id: string;
  type: "order";
  title: string;
  description: string;
  amount: number;
  status: string;
  date: string;
};

interface ReviewQuoteRow {
  id: string;
  client_id: string;
  number: number;
  status: QuoteStatus;
  title: string | null;
  subtotal: number;
  discount: number;
  shipping: number;
  total: number;
  delivery_date?: string | null;
  expires_at: string | null;
  notes: string | null;
  share_enabled: boolean;
  share_token: string | null;
  /* As condições de pagamento: entram na mensagem do WhatsApp no lugar de {{condicoes}}. */
  payment_terms?: unknown;
}

interface ReviewItemRow {
  id: string;
  product_id?: string | null;
  title: string;
  description: string | null;
  quantity: number;
  unit_price: number;
  unit_cost?: number | null;
  unit_type: string | null;
  width_m: number | null;
  height_m: number | null;
  length_m: number | null;
  line_total: number;
  selected_options?: Record<string, unknown> | null;
  /** Valor mínimo do item que pegou nesta linha (migration 194). */
  valor_minimo_aplicado?: number | null;
  valor_sem_minimo?: number | null;
}

interface ReviewClientRow {
  id: string;
  name: string;
  company_name: string | null;
  whatsapp: string | null;
}

interface ReviewClientOption {
  id: string;
  name: string;
  company_name: string | null;
  whatsapp: string | null;
}

interface ReviewEditableItemRow extends ReviewItemRow {
  tempKey?: string;
  unit_price_locked?: boolean;
}

interface ReviewProductAttributeOptionValue {
  id?: string | null;
  label: string;
  price?: number;
  price_applies_per_quantity?: boolean | null;
  stock?: number;
  is_required?: boolean;
  position?: number;
}

interface ReviewProductAttributeValue {
  id?: string | null;
  name: string;
  allow_multiple?: boolean | null;
  is_required?: boolean | null;
  position?: number | null;
  options: Array<string | ReviewProductAttributeOptionValue>;
}

interface ReviewProductVariationValue {
  id?: string | null;
  combination?: Record<string, string> | null;
  stock?: number | null;
}

interface ReviewProductOption {
  id: string;
  name: string;
  /* Digital fica para casar item que veio da loja, mas não é sugerido. */
  product_kind?: string | null;
  price: number | null;
  price_on_request?: boolean | null;
  use_variation_price_only?: boolean | null;
  cost_total?: number | null;
  description?: string | null;
  unit_type?: string | null;
  product_price_tiers?: ProductPriceTier[] | null;
  min_sale_qty_enabled?: boolean | null;
  min_sale_qty?: number | null;
  max_sale_qty_enabled?: boolean | null;
  max_sale_qty?: number | null;
  allowed_sale_qty_enabled?: boolean | null;
  allowed_sale_quantities?: number[] | null;
  inventory_scope?: "product" | "option" | "variant" | null;
  inventory_attribute_name?: string | null;
  allow_negative_stock?: boolean | null;
  track_inventory?: boolean | null;
  product_attributes?: ReviewProductAttributeValue[] | null;
  product_variations?: ReviewProductVariationValue[] | null;
  valor_minimo_item?: number | null;
  valor_minimo_orcamentos?: boolean | null;
}

interface ReviewProfileRow {
  id: string;
  slug: string | null;
  custom_domain?: string | null;
  custom_domain_verified?: boolean | null;
  quote_share_link_expires_enabled?: boolean | null;
  quote_share_link_expires_days?: number | null;
}

type ClientJoin = { name: string; company_name: string | null };
type OrderQueryRow = {
  id: string;
  number: number;
  status: string | null;
  total_amount: number | null;
  paid_amount: number | null;
  financial_status: string | null;
  created_at: string;
  clients: ClientJoin | ClientJoin[] | null;
};

type PaymentRow = {
  amount: number | null;
  payment_date: string | null;
};

function firstOrNull<T>(value: T | T[] | null | undefined): T | null {
  if (!value) return null;
  return Array.isArray(value) ? value[0] ?? null : value;
}

function normalizeDigits(value: string) {
  return value.replace(/\D/g, "");
}

function formatDateBr(value: string | null | undefined) {
  if (!value) return "";
  const normalized = value.split("T")[0];
  const parts = normalized.split("-");
  if (parts.length === 3 && parts[0].length === 4) {
    const [y, m, d] = parts;
    return `${d}/${m}/${y}`;
  }
  const dt = new Date(value);
  if (!Number.isFinite(dt.getTime())) return normalized;
  return dt.toLocaleDateString("pt-BR");
}

function formatMoney(value: number) {
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value || 0);
}

function formatWhatsAppInput(value: string) {
  const digits = normalizeDigits(value).slice(0, 13);
  if (digits.length <= 2) return digits;
  if (digits.length <= 7) return `(${digits.slice(0, 2)}) ${digits.slice(2)}`;
  if (digits.length <= 11) return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7)}`;
  return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 9)}-${digits.slice(9)}`;
}

function normalizeReviewAttributeOption(option: string | ReviewProductAttributeOptionValue, index: number) {
  if (typeof option === "string") {
    return {
      id: null,
      label: option,
      price: 0,
      price_applies_per_quantity: true,
      stock: null,
      is_required: false,
      position: index,
    };
  }

  return {
    id: option.id ?? null,
    label: option.label,
    price: Number(option.price) || 0,
    price_applies_per_quantity: option.price_applies_per_quantity !== false,
    stock: Number.isFinite(Number(option.stock)) ? Number(option.stock) : null,
    is_required: Boolean(option.is_required),
    position: typeof option.position === "number" ? option.position : index,
  };
}

function getSortedReviewAttributes(product: ReviewProductOption | null) {
  return (product?.product_attributes || [])
    .filter((attribute) => Boolean(attribute?.name))
    .slice()
    .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
}

function getReviewItemVariationMap(item: Pick<ReviewEditableItemRow, "selected_options">) {
  const selectedOptions = item.selected_options as { options?: unknown } | null | undefined;
  const options = Array.isArray(selectedOptions?.options) ? selectedOptions.options : [];
  const map: Record<string, string[]> = {};
  for (const raw of options) {
    if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
    const row = raw as Record<string, unknown>;
    const attributeName = typeof row.attribute_name === "string" ? row.attribute_name : "";
    const label = typeof row.label === "string" ? row.label : "";
    if (!attributeName || !label) continue;
    const list = map[attributeName] || [];
    if (!list.includes(label)) list.push(label);
    map[attributeName] = list;
  }
  return map;
}

function buildReviewSelectedOptionsPayload(
  product: ReviewProductOption,
  selectionMap: Record<string, string[]>
) {
  const attributes = getSortedReviewAttributes(product);
  const inventoryScope = product.inventory_scope || "product";
  const inventoryAttributeName = (product.inventory_attribute_name || "").trim().toLowerCase();
  const payloadOptions: Array<{
    option_id: string | null;
    attribute_name: string;
    label: string;
    price: number;
    price_applies_per_quantity: boolean;
    affects_stock: boolean;
  }> = [];

  for (const attribute of attributes) {
    const normalizedOptions = (attribute.options || [])
      .map((option, index) => normalizeReviewAttributeOption(option, index))
      .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
    const selectedLabels = selectionMap[attribute.name] || [];
    for (const selectedLabel of selectedLabels) {
      const selectedOption = normalizedOptions.find((option) => option.label === selectedLabel);
      if (!selectedOption) continue;
      payloadOptions.push({
        option_id: selectedOption.id || null,
        attribute_name: attribute.name,
        label: selectedOption.label,
        price: Number(selectedOption.price) || 0,
        price_applies_per_quantity: selectedOption.price_applies_per_quantity !== false,
        affects_stock:
          inventoryScope === "option" && attribute.name.trim().toLowerCase() === inventoryAttributeName,
      });
    }
  }

  if (!payloadOptions.length) return null;

  return {
    inventory_scope: inventoryScope,
    inventory_attribute_name: inventoryScope === "option" ? product.inventory_attribute_name || null : null,
    options: payloadOptions,
  };
}

function getReviewSelectedOptionsPriceBreakdown(item: ReviewEditableItemRow, product?: ReviewProductOption | null) {
  if (!product) return { perQuantity: 0, oneTime: 0 };
  const selectedMap = getReviewItemVariationMap(item);
  const attributes = getSortedReviewAttributes(product);
  let perQuantity = 0;
  let oneTime = 0;

  for (const attribute of attributes) {
    const selectedLabels = selectedMap[attribute.name] || [];
    if (!selectedLabels.length) continue;
    const normalizedOptions = (attribute.options || [])
      .map((option, index) => normalizeReviewAttributeOption(option, index))
      .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
    for (const selectedLabel of selectedLabels) {
      const selectedOption = normalizedOptions.find((option) => option.label === selectedLabel);
      if (!selectedOption) continue;
      const optionPrice = Number(selectedOption.price) || 0;
      if (selectedOption.price_applies_per_quantity === false) {
        oneTime += optionPrice;
      } else {
        perQuantity += optionPrice;
      }
    }
  }

  return { perQuantity, oneTime };
}

function effectiveReviewQuantity(
  item: Pick<ReviewEditableItemRow, "quantity" | "unit_type" | "width_m" | "height_m" | "length_m">
) {
  const quantity = Number(item.quantity) || 0;
  if (quantity <= 0) return 0;

  if (item.unit_type === "square_meter") {
    const area = (Number(item.width_m) || 0) * (Number(item.height_m) || 0);
    return area > 0 ? quantity * area : quantity;
  }

  if (item.unit_type === "linear_meter" || item.unit_type === "meter") {
    const length = Number(item.length_m) || 0;
    return length > 0 ? quantity * length : quantity;
  }

  return quantity;
}

function getReviewAllowedQuantities(product?: ReviewProductOption | null) {
  if (!product) return [] as number[];
  return Array.isArray(product.allowed_sale_quantities)
    ? product.allowed_sale_quantities
        .map((value) => Number(value))
        .filter((value) => Number.isFinite(value) && value > 0)
        .sort((a, b) => a - b)
    : [];
}

function getReviewMinimumItemQuantity(product?: ReviewProductOption | null) {
  if (!product) return 1;
  const allowedQuantities = getReviewAllowedQuantities(product);
  if (Boolean(product.allowed_sale_qty_enabled) && allowedQuantities.length > 0) {
    return Number(allowedQuantities[0].toFixed(3));
  }
  if (Boolean(product.min_sale_qty_enabled)) {
    const minQty = Number(product.min_sale_qty);
    if (Number.isFinite(minQty) && minQty > 0) return Number(minQty.toFixed(3));
  }
  return 1;
}

function resolveReviewProductUnitPrice(item: ReviewEditableItemRow, product: ReviewProductOption) {
  if (product.price_on_request) return 0;
  const qty = effectiveReviewQuantity(item);
  const basePrice = resolveTierPrice(Number(product.price) || 0, qty, product.product_price_tiers || []).unitPrice;
  const optionPrices = getReviewSelectedOptionsPriceBreakdown(item, product);
  const safeQty = qty > 0 ? qty : 1;
  const optionsAdjustment = optionPrices.perQuantity + optionPrices.oneTime / safeQty;
  return Math.max(0, Number((basePrice + optionsAdjustment).toFixed(2)));
}

/* O preço da linha e, por último, o valor mínimo do item: a linha inteira
   comparada sozinha com ele. Com o mínimo, o preço por medida vira mínimo ÷
   quantidade e a linha é gravada no valor exato do mínimo. */
function resolveReviewProductLine(item: ReviewEditableItemRow, product: ReviewProductOption) {
  const unitPrice = resolveReviewProductUnitPrice(item, product);
  const minimo = valorMinimoDoItem(product, "orcamentos");
  const qty = effectiveReviewQuantity(item);
  const automatico = Math.round(qty * unitPrice * 100) / 100;
  if (minimo === null || automatico >= minimo) {
    return { unit_price: unitPrice, valor_minimo_aplicado: null, valor_sem_minimo: null };
  }
  const safeQty = qty > 0 ? qty : 1;
  return {
    unit_price: Math.round((minimo / safeQty) * 1e6) / 1e6,
    valor_minimo_aplicado: minimo,
    valor_sem_minimo: automatico,
  };
}

/** O que a linha vale: o mínimo do item quando pegou; senão quantidade × preço. */
function totalDaLinhaDaRevisao(item: ReviewEditableItemRow) {
  if (!item.unit_price_locked && item.valor_minimo_aplicado != null && Number(item.valor_minimo_aplicado) > 0) {
    return Number(item.valor_minimo_aplicado);
  }
  return Math.max(0, effectiveReviewQuantity(item)) * Math.max(0, Number(item.unit_price) || 0);
}

function formatInteger(value: number) {
  return new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 0 }).format(value || 0);
}

function AnimatedMetricValue({
  value,
  format,
  hidden,
}: {
  value: number;
  format: "currency" | "number";
  hidden?: boolean;
}) {
  const [displayValue, setDisplayValue] = useState(0);

  useEffect(() => {
    if (hidden) return;
    const startValue = displayValue;
    const targetValue = value;
    if (startValue === targetValue) return;
    const startTime = performance.now();
    const duration = 520;
    let raf = 0;

    const tick = (now: number) => {
      const progress = Math.min((now - startTime) / duration, 1);
      const eased = 1 - Math.pow(1 - progress, 3);
      setDisplayValue(startValue + (targetValue - startValue) * eased);
      if (progress < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value, hidden]); // eslint-disable-line react-hooks/exhaustive-deps

  if (hidden) return <>••••••</>;
  return <>{format === "currency" ? formatMoney(displayValue) : formatInteger(displayValue)}</>;
}

function startOfDay(date: Date) {
  const d = new Date(date);
  d.setHours(0, 0, 0, 0);
  return d;
}

function addDays(date: Date, days: number) {
  const d = new Date(date);
  d.setDate(d.getDate() + days);
  return d;
}

function parsePaymentDate(value: unknown): Date | null {
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
  if (typeof value !== "string") return null;

  const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
  if (dateOnly) {
    const year = Number(dateOnly[1]);
    const month = Number(dateOnly[2]);
    const day = Number(dateOnly[3]);
    const d = new Date(year, month - 1, day, 0, 0, 0, 0);
    return Number.isNaN(d.getTime()) ? null : d;
  }

  const d = new Date(value);
  return Number.isNaN(d.getTime()) ? null : d;
}

function isCanceledOrderStatus(status: string | null | undefined) {
  const normalized = String(status || "").trim().toLowerCase();
  return normalized === "canceled" || normalized === "cancelled";
}

function formatShortDayLabel(date: Date, days: number) {
  if (days === 1) return "Hoje";
  return new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "2-digit" }).format(date);
}

function generateShareToken() {
  const bytes = new Uint8Array(24);
  crypto.getRandomValues(bytes);
  return Array.from(bytes)
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}


const AVAILABLE_QUICK_ACTIONS = [
  { id: 'new_quote', label: 'Novo Orçamento', href: '/dashboard/quotes/new', icon: FileDown },
  { id: 'new_product', label: 'Cadastrar Produto', href: '/dashboard/products/new', icon: Package },
  { id: 'receivables', label: 'Contas a Receber', href: '/dashboard/financial/receivables', icon: DollarSign },
  /* Vai para o PDV, nao para /dashboard/orders/new: essa rota nunca existiu
     e caia na pagina [id], que mandava a string "new" para o Postgres e
     estourava 22P02. Pedido sem orcamento tambem nao existe no modelo
     (orders.quote_id e NOT NULL) — o PDV e o caminho que gera os dois de
     uma vez, sem etapa de aprovacao. */
  /* `id` continua 'new_order' de proposito: e ele que fica gravado no
     localStorage de quem ja escolheu essa acao. Trocar o id apagaria o
     atalho do painel dessas pessoas. */
  { id: 'new_order', label: 'PDV', href: '/dashboard/pdv', icon: Plus },
  { id: 'catalog', label: 'Ver Catálogo', href: '/dashboard/catalog', icon: ExternalLink },
  { id: 'reports', label: 'Relatórios', href: '/dashboard/reports', icon: BarChart3 }
];

const QUICK_ACTIONS_LEGACY_KEY = "ks-quick-actions";
const DEFAULT_QUICK_ACTIONS = ["new_quote", "new_product", "receivables"];

/** Chave por usuário: num navegador compartilhado, cada conta tem seu painel. */
const quickActionsKey = (userId: string | null) =>
  userId ? `${QUICK_ACTIONS_LEGACY_KEY}:${userId}` : QUICK_ACTIONS_LEGACY_KEY;

/**
 * localStorage lança em modo privado, com armazenamento cheio ou com dados de
 * site bloqueados. Sem try/catch a escrita falha calada: a tela mostra a
 * alteração e ela some no refresh. Estes wrappers tornam a falha visível.
 */
function readStoredJson<T>(key: string): T | null {
  try {
    const raw = window.localStorage.getItem(key);
    return raw === null ? null : (JSON.parse(raw) as T);
  } catch {
    return null;
  }
}

function writeStoredJson(key: string, value: unknown): boolean {
  try {
    window.localStorage.setItem(key, JSON.stringify(value));
    return true;
  } catch {
    return false;
  }
}

/** Tons dos cartões de métrica, na ordem em que aparecem. */
const STAT_TONES = ["ks-stat-violet", "ks-stat-sky", "ks-stat-emerald", "ks-stat-lime"];

/** Cada ação rápida ganha um tom próprio — a cor vira o identificador visual. */
const QUICK_ACTION_TONES: Record<string, string> = {
  new_quote: "ks-tile-violet",
  new_product: "ks-tile-sky",
  receivables: "ks-tile-emerald",
  new_order: "ks-tile-amber",
  catalog: "ks-tile-pink",
  reports: "ks-tile-teal",
};

/** Rótulo e tom do status financeiro, alinhados com a tela de Contas a Receber. */
const ORDER_STATUS_META: Record<string, { label: string; chip: string }> = {
  paid: { label: "Pago", chip: "ks-chip-success" },
  partially_paid: { label: "Parcial", chip: "ks-chip-warning" },
  unpaid: { label: "Em aberto", chip: "ks-chip-danger" },
  canceled: { label: "Cancelado", chip: "ks-chip-neutral" },
};

/** Tons rotativos dos cards de pedido, no espírito dos logos coloridos da referência. */
const ORDER_TONES = [
  "ks-tile-violet",
  "ks-tile-sky",
  "ks-tile-emerald",
  "ks-tile-amber",
  "ks-tile-pink",
  "ks-tile-teal",
];

const aiHeaderTexts = [
  "Revise e aprove",
  "Simples e fácil",
  "A IA da Ktalogu te ajuda 😉"
];

export default function DashboardPage() {
  const { pode } = usePermissoes();
  const podeMexerEmOrcamentos = pode("quotes.write");
  /* Duas chaves, dois papeis: uma abre o assistente, a outra chama a IA —
     que e o que as rotas sempre exigiram. Sem a segunda, o botao some em vez
     de devolver 403 depois do clique. */
  const podeVerIA = pode("ia.read");
  const podeGerarComIA = pode("ia.write");
  const podeMexerNoCatalogo = pode("catalog.store.write");

  const router = useRouter();
  const [userName, setUserName] = useState("");
  const [userId, setUserId] = useState<string | null>(null);
  const [range, setRange] = useState("week");
  const [hiddenStats, setHiddenStats] = useState<Record<number, boolean>>({});
  const [iaOrcamentoText, setIaOrcamentoText] = useState("");
  const [iaOrcamentoImage, setIaOrcamentoImage] = useState<string | null>(null);
  const [iaOrcamentoImageName, setIaOrcamentoImageName] = useState("");
  const [iaCreating, setIaCreating] = useState(false);
  const [iaError, setIaError] = useState("");
  const [isReviewModalOpen, setIsReviewModalOpen] = useState(false);
  const [reviewLoading, setReviewLoading] = useState(false);
  const [reviewError, setReviewError] = useState("");
  const [reviewQuote, setReviewQuote] = useState<ReviewQuoteRow | null>(null);
  const [reviewItems, setReviewItems] = useState<ReviewItemRow[]>([]);
  const [reviewClient, setReviewClient] = useState<ReviewClientRow | null>(null);
  const [reviewClientOptions, setReviewClientOptions] = useState<ReviewClientOption[]>([]);
  const [reviewClientSearch, setReviewClientSearch] = useState("");
  const [reviewDraftClientId, setReviewDraftClientId] = useState("");
  const [reviewDraftWhatsApp, setReviewDraftWhatsApp] = useState("");
  const [reviewDraftNotes, setReviewDraftNotes] = useState("");
  const [reviewDraftDeliveryDate, setReviewDraftDeliveryDate] = useState("");
  const [reviewDraftItems, setReviewDraftItems] = useState<ReviewEditableItemRow[]>([]);
  const [reviewProducts, setReviewProducts] = useState<ReviewProductOption[]>([]);
  const [reviewMoneyDrafts, setReviewMoneyDrafts] = useState<Record<string, string>>({});
  const [reviewMeasureDrafts, setReviewMeasureDrafts] = useState<
    Record<string, { width_m: string; height_m: string; length_m: string }>
  >({});
  const [reviewEditingClient, setReviewEditingClient] = useState(false);
  const [reviewEditingNotes, setReviewEditingNotes] = useState(false);
  const [reviewEditingDeliveryDate, setReviewEditingDeliveryDate] = useState(false);
  const [reviewEditingItemId, setReviewEditingItemId] = useState<string | null>(null);
  const [reviewCreatingClient, setReviewCreatingClient] = useState(false);
  const [reviewNewClientName, setReviewNewClientName] = useState("");
  const [reviewNewClientCompany, setReviewNewClientCompany] = useState("");
  const [reviewNewClientWhatsApp, setReviewNewClientWhatsApp] = useState("");
  const [reviewSaving, setReviewSaving] = useState(false);
  const [reviewProfile, setReviewProfile] = useState<ReviewProfileRow | null>(null);
  const [reviewApproved, setReviewApproved] = useState(false);
  const [sharing, setSharing] = useState(false);
  const [copied, setCopied] = useState(false);
  const [dashboardData, setDashboardData] = useState<{
    totalSales: number;
    activeProducts: number;
    totalViews: number;
    totalReceivedToday: number;
    totalOpenAmount: number;
    ordersCreatedToday: number;
    salesChange: number;
    productsChange: number;
    viewsChange: number;
    orders: any[];
    payments: PaymentRow[];
    recentActivities: RecentActivity[];
  }>({
    totalSales: 0,
    activeProducts: 0,
    totalViews: 0,
    totalReceivedToday: 0,
    totalOpenAmount: 0,
    ordersCreatedToday: 0,
    salesChange: 0,
    productsChange: 0,
    viewsChange: 0,
    orders: [],
    payments: [],
    recentActivities: []
  });

  const [quickActions, setQuickActions] = useState<string[]>(DEFAULT_QUICK_ACTIONS);
  const [isQuickActionsModalOpen, setIsQuickActionsModalOpen] = useState(false);
  const [tempQuickActions, setTempQuickActions] = useState<string[]>([]);
  const [quickActionsError, setQuickActionsError] = useState("");
  
  useEffect(() => {
    const scoped = readStoredJson<string[]>(quickActionsKey(userId));
    const legacy = userId ? readStoredJson<string[]>(QUICK_ACTIONS_LEGACY_KEY) : null;
    const stored = Array.isArray(scoped) ? scoped : Array.isArray(legacy) ? legacy : null;
    if (!stored) return;

    setQuickActions(stored.filter((id) => typeof id === "string"));
    // migra a configuração antiga, sem escopo, para a chave desta conta
    if (userId && !Array.isArray(scoped) && Array.isArray(legacy)) {
      writeStoredJson(quickActionsKey(userId), legacy);
    }
  }, [userId]);

  const [isRangeDropdownOpen, setIsRangeDropdownOpen] = useState(false);
  const rangeDropdownRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (rangeDropdownRef.current && !rangeDropdownRef.current.contains(event.target as Node)) {
        setIsRangeDropdownOpen(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);
  
  const rangeOptions = useMemo(() => [
    { value: "day", label: "Hoje", days: 1 },
    { value: "week", label: "7 dias", days: 7 },
    { value: "quinzena", label: "15 dias", days: 15 },
    { value: "month", label: "30 dias", days: 30 },
  ], []);
  
  // Gerar estatísticas com dados reais
  const stats = useMemo<StatCard[]>(() => [
    {
      title: "Entradas do dia",
      rawValue: dashboardData.totalReceivedToday,
      format: "currency",
      change: "Hoje",
      icon: DollarSign,
      description: "valores recebidos hoje",
      variant: "primary",
      sensitive: true,
    },
    {
      title: "A receber",
      rawValue: dashboardData.totalOpenAmount,
      format: "currency",
      change: "Em aberto",
      icon: Package,
      description: "valores pendentes",
      variant: "light",
      sensitive: true,
    },
    {
      title: "Pedidos do dia",
      rawValue: dashboardData.ordersCreatedToday,
      format: "number",
      change: "Hoje",
      icon: BarChart3,
      description: "gerados hoje",
      variant: "light",
    },
  ], [dashboardData]);
  
  const chartData = useMemo(() => {
    const option = rangeOptions.find((item) => item.value === range);
    const days = option?.days ?? 7;
    const todayStart = startOfDay(new Date());
    const startDate = addDays(todayStart, -(days - 1));
    const orders = dashboardData.orders ?? [];
    const values = Array.from({ length: days }, (_, index) => {
      const dayStart = addDays(startDate, index);
      const dayEnd = addDays(dayStart, 1);
      return orders.reduce((sum, order) => {
        /* Pedido cancelado nao e receita. Ele continuava somando aqui, entao o
           grafico mostrava dinheiro que a grafica devolveu ou nunca recebeu. */
        if (isCanceledOrderStatus(order.status)) return sum;
        const dt = new Date(order.created_at);
        if (!Number.isFinite(dt.getTime())) return sum;
        if (dt >= dayStart && dt < dayEnd) return sum + (Number(order.total_amount) || 0);
        return sum;
      }, 0);
    });
    const labels = Array.from({ length: days }, (_, index) => {
      const dayStart = addDays(startDate, index);
      return formatShortDayLabel(dayStart, days);
    });
    const maxValue = Math.max(...values, 1);
    const paddingX = 6;
    const paddingYTop = 10;
    const paddingYBottom = 14;
    const baseline = 100 - paddingYBottom;
    const points = values.map((value, index) => {
      const x = days === 1
        ? 50
        : paddingX + (index / Math.max(days - 1, 1)) * (100 - paddingX * 2);
      const y = paddingYTop + (1 - value / maxValue) * (baseline - paddingYTop);
      return { x, y, value, label: labels[index] };
    });
    return { days, values, labels, points, baseline, maxValue };
  }, [dashboardData.orders, range, rangeOptions]);

  useEffect(() => {
    const stored = readStoredJson<Record<number, boolean>>("ks-hidden-stats");
    if (stored) setHiddenStats(stored);
  }, []);

  useEffect(() => {
    async function loadUser() {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (user) {
        setUserId(user.id);
        const ctx = await getCompanyContext(supabase, user);
        const isEmployee = shouldUseEmployeeUi(ctx, user.id);

        if (isEmployee) {
          const { data: employeeProfile } = await supabase
            .from("employee_profiles")
            .select("full_name")
            .eq("user_id", user.id)
            .maybeSingle();

          if (employeeProfile?.full_name) {
            const firstName = String(employeeProfile.full_name).split(" ")[0];
            setUserName(firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase());
            return;
          }
        }

        const name = user.user_metadata?.full_name || user.user_metadata?.name;
        if (name) {
          const firstName = String(name).split(" ")[0];
          setUserName(firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase());
          return;
        }

        const { data: profile } = await supabase
          .from("profiles")
          .select("store_name")
          .eq("id", user.id)
          .maybeSingle();

        if (profile?.store_name) {
          const firstName = String(profile.store_name).split(" ")[0];
          setUserName(firstName.charAt(0).toUpperCase() + firstName.slice(1).toLowerCase());
          return;
        }

        const emailName = user.email?.split("@")[0] || "Usuário";
        setUserName(emailName.charAt(0).toUpperCase() + emailName.slice(1).toLowerCase());
      }
    }
    loadUser();
    loadDashboardData();
  }, []);

  async function loadDashboardData() {
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) {
        return;
      }

      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];
      
      // Buscar dados de vendas (orders) com informações completas
      const { data: ordersData, error: ordersError } = await supabase
        .from('orders')
        .select('id, number, status, total_amount, paid_amount, financial_status, created_at, clients(name, company_name)')
        .in('user_id', tenantIds)
        .order('created_at', { ascending: false });
      
      if (ordersError) throw ordersError;

      const { data: paymentsData, error: paymentsError } = await supabase
        .from('payments')
        .select('amount, payment_date')
        .in('user_id', tenantIds)
        .order('payment_date', { ascending: false });

      if (paymentsError) throw paymentsError;
      
      // Buscar dados de produtos
      const { data: productsData, error: productsError } = await supabase
        .from('products')
        .select('id, created_at, active')
        .in('user_id', tenantIds)
        .neq("product_kind", "digital")
        .eq('active', true);
      
      if (productsError) throw productsError;
      
      // Buscar dados de visualizações (se existir uma tabela de analytics)
      // Por enquanto, vamos usar um valor baseado no número de pedidos como proxy
      const totalViews = ordersData ? ordersData.length * 100 : 3200;
      
      // Calcular totais
      const totalSales =
        ((ordersData as OrderQueryRow[] | null) ?? [])
          .filter((order) => !isCanceledOrderStatus(order.status))
          .reduce((sum, order) => sum + (Number(order.paid_amount) || 0), 0) || 0;
      const activeProducts = productsData?.length || 0;
      const now = new Date();
      const todayStart = startOfDay(now);
      const tomorrowStart = addDays(todayStart, 1);
      const totalReceivedToday = ((paymentsData as PaymentRow[] | null) ?? [])
        .filter((payment) => {
          const dt = parsePaymentDate(payment.payment_date);
          if (!dt) return false;
          return dt >= todayStart && dt < tomorrowStart;
        })
        .reduce((sum, payment) => sum + (Number(payment.amount) || 0), 0);
      const totalOpenAmount = ((ordersData as OrderQueryRow[] | null) ?? [])
        .filter((order) => !isCanceledOrderStatus(order.status) && order.financial_status !== "paid")
        .reduce((sum, order) => sum + (Number(order.total_amount) - (Number(order.paid_amount) || 0)), 0);
      const ordersCreatedToday = ((ordersData as OrderQueryRow[] | null) ?? [])
        .filter((order) => {
          /* Mesma regra do grafico: cancelado sai da conta. A venda cancelada
             continuava no contador do dia, e o numero nunca batia com a lista
             de pedidos. */
          if (isCanceledOrderStatus(order.status)) return false;
          const dt = new Date(order.created_at);
          if (!Number.isFinite(dt.getTime())) return false;
          return dt >= todayStart && dt < tomorrowStart;
        })
        .length;
      
      // Calcular mudanças (baseado em dados históricos)
      const salesChange = ordersData && ordersData.length > 10 ? 15 : 8;
      const productsChange = productsData && productsData.length > 20 ? 2 : 1;
      const viewsChange = ordersData && ordersData.length > 5 ? 24 : 12;
      
      // Últimas movimentações (últimos pedidos com informações completas)
      const recentActivities: RecentActivity[] = ((ordersData as OrderQueryRow[] | null) ?? []).slice(0, 5).map((order) => {
        const client = firstOrNull(order.clients);
        const canceled = isCanceledOrderStatus(order.status);
        return {
          id: order.id,
          type: "order",
          title: `Pedido #${order.number}`,
          description: client?.company_name || client?.name || 'Cliente não informado',
          amount: order.total_amount ?? 0,
          /* Pedido cancelado aparecia aqui com o selo financeiro dele, quase
             sempre "Em aberto" em vermelho, como se ainda houvesse o que
             receber. */
          status: canceled ? 'canceled' : (order.financial_status ?? 'unpaid'),
          date: order.created_at
        };
      });
      
      setDashboardData({
        totalSales,
        activeProducts,
        totalViews,
        totalReceivedToday,
        totalOpenAmount,
        ordersCreatedToday,
        salesChange,
        productsChange,
        viewsChange,
        orders: ordersData ?? [],
        payments: (paymentsData as PaymentRow[] | null) ?? [],
        recentActivities
      });
      
    } catch (error) {
      console.error('Erro ao carregar dados da dashboard:', error);
    }
  }

  const publicBaseUrl = useMemo(() => {
    const origin = typeof window !== "undefined" ? window.location.origin : "https://ktalogu.com.br";
    const resolved = process.env.NEXT_PUBLIC_PUBLIC_CATALOG_BASE_URL || origin;
    const normalized = resolved.replace(":3002", ":3001").replace(/\/\/admin\./, "//");
    return normalized.replace(/\/$/, "");
  }, []);

  const reviewClientLabel = useMemo(() => {
    if (!reviewClient) return "";
    return reviewClient.company_name ? `${reviewClient.company_name} — ${reviewClient.name}` : reviewClient.name;
  }, [reviewClient]);

  const filteredReviewClients = useMemo(() => {
    const term = reviewClientSearch.trim().toLowerCase();
    if (!term) return reviewClientOptions.slice(0, 8);
    return reviewClientOptions
      .filter((client) =>
        `${client.company_name || ""} ${client.name} ${client.whatsapp || ""}`.toLowerCase().includes(term)
      )
      .slice(0, 8);
  }, [reviewClientOptions, reviewClientSearch]);

  const selectedReviewClient = useMemo(() => {
    return reviewClientOptions.find((client) => client.id === reviewDraftClientId) || reviewClient || null;
  }, [reviewClient, reviewClientOptions, reviewDraftClientId]);

  const reviewClientSelectOptions = useMemo(
    () => [
      { value: "", label: "Sem cliente" },
      ...reviewClientOptions.map((client) => ({
        value: client.id,
        label: client.company_name ? `${client.company_name} - ${client.name}` : client.name,
        description: client.whatsapp || undefined,
      })),
    ],
    [reviewClientOptions]
  );

  const reviewDraftTotal = useMemo(() => {
    return reviewDraftItems.reduce((sum, item) => sum + totalDaLinhaDaRevisao(item), 0);
  }, [reviewDraftItems]);

  const reviewProductsById = useMemo(
    () => new Map(reviewProducts.map((product) => [product.id, product])),
    [reviewProducts]
  );

  const [currentTextIndex, setCurrentTextIndex] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCurrentTextIndex((prev) => (prev + 1) % aiHeaderTexts.length);
    }, 4000);
    return () => clearInterval(interval);
  }, []);

  const isDraftQuote = reviewQuote?.id === "draft";
  const hasChanges = useMemo(() => {
    if (!reviewQuote || isDraftQuote) return true;
    if (reviewDraftClientId !== reviewQuote.client_id) return true;
    if (reviewDraftNotes !== (reviewQuote.notes || "")) return true;
    const currentDelivery = reviewQuote.delivery_date ? String(reviewQuote.delivery_date).slice(0, 10) : "";
    if (reviewDraftDeliveryDate !== currentDelivery) return true;
    if (reviewDraftWhatsApp !== formatWhatsAppInput(reviewClient?.whatsapp || "")) return true;
    
    if (reviewDraftItems.length !== reviewItems.length) return true;
    for (let i = 0; i < reviewDraftItems.length; i++) {
      const draftItem = reviewDraftItems[i];
      const origItem = reviewItems[i];
      if (draftItem.product_id !== origItem.product_id) return true;
      if (draftItem.quantity !== origItem.quantity) return true;
      if (draftItem.unit_price !== origItem.unit_price) return true;
      if (draftItem.width_m !== origItem.width_m) return true;
      if (draftItem.height_m !== origItem.height_m) return true;
      if (draftItem.length_m !== origItem.length_m) return true;
      if (draftItem.description !== origItem.description) return true;
      if (draftItem.title !== origItem.title) return true;
      if (draftItem.unit_type !== origItem.unit_type) return true;
    }
    return false;
  }, [reviewQuote, isDraftQuote, reviewDraftClientId, reviewDraftNotes, reviewDraftDeliveryDate, reviewDraftWhatsApp, reviewClient, reviewDraftItems, reviewItems]);

  useEffect(() => {
    setReviewMoneyDrafts((prev) => {
      const next = { ...prev };
      for (const item of reviewDraftItems) {
        const formatted = formatMoneyInput(item.unit_price || 0);
        if (!next[item.id] || parseMoneyInput(next[item.id]) !== (item.unit_price || 0)) {
          next[item.id] = formatted;
        }
      }
      Object.keys(next).forEach((key) => {
        if (!reviewDraftItems.some((item) => item.id === key)) delete next[key];
      });
      return next;
    });

    setReviewMeasureDrafts((prev) => {
      const next = { ...prev };
      for (const item of reviewDraftItems) {
        const current = prev[item.id];
        const fallback = {
          width_m: formatMeasureInput(item.width_m),
          height_m: formatMeasureInput(item.height_m),
          length_m: formatMeasureInput(item.length_m),
        };
        next[item.id] = {
          width_m:
            !current || Math.abs(parseMeasureInput(current.width_m) - (item.width_m || 0)) > 0.0005
              ? fallback.width_m
              : current.width_m,
          height_m:
            !current || Math.abs(parseMeasureInput(current.height_m) - (item.height_m || 0)) > 0.0005
              ? fallback.height_m
              : current.height_m,
          length_m:
            !current || Math.abs(parseMeasureInput(current.length_m) - (item.length_m || 0)) > 0.0005
              ? fallback.length_m
              : current.length_m,
        };
      }
      Object.keys(next).forEach((key) => {
        if (!reviewDraftItems.some((item) => item.id === key)) delete next[key];
      });
      return next;
    });
  }, [reviewDraftItems]);

  const quoteTitle = useMemo(() => {
    if (!reviewQuote) return "Orçamento";
    if (reviewQuote.id === "draft") return "Novo Orçamento";
    return `Orçamento #${reviewQuote.number}`;
  }, [reviewQuote]);

  async function openDraftReviewModal(draftPayload: any) {
    setIsReviewModalOpen(true);
    setReviewLoading(true);
    setReviewError("");
    setReviewApproved(false);
    setCopied(false);
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) throw new Error("Usuário não autenticado");
      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];

      const [
        { data: clientData, error: clientErr },
        { data: clientsOptionsData, error: clientsOptionsErr },
        { data: productsData, error: productsErr },
        { data: profileData, error: profileErr },
        { data: domainData, error: domainErr },
      ] = await Promise.all([
        draftPayload.client_id ? supabase
          .from("clients")
          .select("id,name,company_name,whatsapp")
          .eq("id", draftPayload.client_id)
          .in("user_id", tenantIds)
          .single() : Promise.resolve({ data: null, error: null }),
        supabase
          .from("clients")
          .select("id,name,company_name,whatsapp")
          .in("user_id", tenantIds)
          .eq("is_deleted", false)
          .order("company_name", { ascending: true, nullsFirst: false })
          .order("name", { ascending: true }),
        supabase
          .from("products")
          .select(`id,name,price,description,unit_type,product_kind,price_on_request,use_variation_price_only,cost_total,min_sale_qty_enabled,min_sale_qty,max_sale_qty_enabled,max_sale_qty,allowed_sale_qty_enabled,allowed_sale_quantities,inventory_scope,inventory_attribute_name,allow_negative_stock,track_inventory,product_attributes(name,allow_multiple,is_required,position,options),product_variations(combination,stock),product_price_tiers(min_qty,max_qty,unit_price,sort_order,active),${COLUNAS_DO_VALOR_MINIMO}`)
          .in("user_id", tenantIds)
          .eq("active", true)
          .order("name", { ascending: true })
          .limit(200),
        supabase
          .from("profiles")
          .select("id,slug,quote_share_link_expires_enabled,quote_share_link_expires_days")
          .eq("id", ctx.ownerId || user.id)
          .single(),
        supabase
          .from("profile_custom_domains")
          .select("domain,verified")
          .eq("profile_id", ctx.ownerId || user.id)
          .maybeSingle(),
      ]);

      if (clientErr && clientErr.code !== "PGRST116") throw clientErr;
      if (clientsOptionsErr) throw clientsOptionsErr;
      if (productsErr) throw productsErr;
      if (profileErr) throw profileErr;
      if (domainErr && domainErr.code !== "PGRST116" && domainErr.code !== "42P01") throw domainErr;

      const resolvedItems = (draftPayload.items || []).map((item: any) => ({
        id: crypto.randomUUID(), // Gerar ID temporário para o draft
        product_id: item.product_id || null,
        title: item.title,
        description: item.description || null,
        quantity: item.quantity || 1,
        unit_price: item.unit_price || 0,
        unit_cost: item.unit_cost || 0,
        unit_type: item.unit_type || "unit",
        width_m: item.width_m || null,
        height_m: item.height_m || null,
        length_m: item.length_m || null,
        line_total: item.line_total || 0,
        selected_options: item.selected_options || null,
        valor_minimo_aplicado: item.valor_minimo_aplicado ?? null,
        valor_sem_minimo: item.valor_sem_minimo ?? null,
        unit_price_locked: false,
      }));

      const resolvedClient = (clientData as ReviewClientRow) || null;
      const resolvedClientsOptions = (clientsOptionsData as ReviewClientOption[]) || [];
      const resolvedProducts = (productsData as ReviewProductOption[]) || [];

      const isFallbackClient = resolvedClient?.company_name === "Orcamento rapido" || resolvedClient?.name?.toLowerCase() === "cliente pendente";

      setReviewQuote({
        id: "draft",
        client_id: draftPayload.client_id || "",
        number: 0,
        status: draftPayload.status || "draft",
        title: draftPayload.title || null,
        subtotal: draftPayload.subtotal || 0,
        discount: draftPayload.discount || 0,
        shipping: draftPayload.shipping || 0,
        total: draftPayload.total || 0,
        expires_at: draftPayload.expires_at || null,
        notes: draftPayload.notes || null,
        share_enabled: false,
        share_token: null,
      });

      setReviewItems(resolvedItems);
      setReviewDraftItems(resolvedItems);
      setReviewClient(resolvedClient);
      setReviewClientOptions(resolvedClientsOptions);
      setReviewProducts(resolvedProducts);
      setReviewClientSearch("");
      setReviewDraftClientId(resolvedClient?.id || "");
      setReviewDraftWhatsApp(formatWhatsAppInput(draftPayload.client_whatsapp || (isFallbackClient ? "" : resolvedClient?.whatsapp) || ""));
      setReviewDraftNotes(draftPayload.notes || "");
      setReviewDraftDeliveryDate(draftPayload.delivery_date || "");
      setReviewEditingClient(false);
      setReviewEditingNotes(false);
      setReviewEditingDeliveryDate(false);
      setReviewEditingItemId(null);
      setReviewCreatingClient(false);
      setReviewNewClientName("");
      setReviewNewClientCompany("");
      setReviewNewClientWhatsApp("");
      
      const baseProfile = (profileData as ReviewProfileRow | null) || null;
      setReviewProfile(
        baseProfile
          ? {
              ...baseProfile,
              custom_domain: (domainData as { domain?: string | null } | null)?.domain || null,
              custom_domain_verified: Boolean((domainData as { verified?: boolean | null } | null)?.verified),
            }
          : null
      );
    } catch (err) {
      console.error("Erro ao carregar rascunho de IA para revisão:", err);
      setReviewError("Falha ao carregar rascunho.");
    } finally {
      setReviewLoading(false);
    }
  }

  async function openReviewModal(quoteId: string) {
    setIsReviewModalOpen(true);
    setReviewLoading(true);
    setReviewError("");
    setReviewApproved(false);
    setCopied(false);
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) throw new Error("Usuário não autenticado");
      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];

      const { data: quoteData, error: quoteErr } = await supabase
        .from("quotes")
        .select("id,client_id,number,status,title,subtotal,discount,shipping,total,expires_at,notes,share_enabled,share_token,payment_terms")
        .eq("id", quoteId)
        .in("user_id", tenantIds)
        .single();
      if (quoteErr) throw quoteErr;

      const q = quoteData as ReviewQuoteRow;

      const [
        { data: itemsData, error: itemsErr },
        { data: clientData, error: clientErr },
        { data: clientsOptionsData, error: clientsOptionsErr },
        { data: productsData, error: productsErr },
        { data: profileData, error: profileErr },
        { data: domainData, error: domainErr },
      ] = await Promise.all([
        supabase
          .from("quote_items")
          .select("id,product_id,title,description,quantity,unit_price,unit_cost,unit_type,width_m,height_m,length_m,line_total,selected_options,valor_minimo_aplicado,valor_sem_minimo")
          .eq("quote_id", q.id)
          .order("position", { ascending: true }),
        supabase
          .from("clients")
          .select("id,name,company_name,whatsapp")
          .eq("id", q.client_id)
          .in("user_id", tenantIds)
          .single(),
        supabase
          .from("clients")
          .select("id,name,company_name,whatsapp")
          .in("user_id", tenantIds)
          .eq("is_deleted", false)
          .order("company_name", { ascending: true, nullsFirst: false })
          .order("name", { ascending: true }),
        supabase
          .from("products")
          .select(`id,name,price,description,unit_type,product_kind,price_on_request,use_variation_price_only,cost_total,min_sale_qty_enabled,min_sale_qty,max_sale_qty_enabled,max_sale_qty,allowed_sale_qty_enabled,allowed_sale_quantities,inventory_scope,inventory_attribute_name,allow_negative_stock,track_inventory,product_attributes(name,allow_multiple,is_required,position,options),product_variations(combination,stock),product_price_tiers(min_qty,max_qty,unit_price,sort_order,active),${COLUNAS_DO_VALOR_MINIMO}`)
          .in("user_id", tenantIds)
          .eq("active", true)
          .order("name", { ascending: true })
          .limit(200),
        supabase
          .from("profiles")
          .select("id,slug,quote_share_link_expires_enabled,quote_share_link_expires_days")
          .eq("id", ctx.ownerId || user.id)
          .single(),
        supabase
          .from("profile_custom_domains")
          .select("domain,verified")
          .eq("profile_id", ctx.ownerId || user.id)
          .maybeSingle(),
      ]);
      if (itemsErr) throw itemsErr;
      if (clientErr) throw clientErr;
      if (clientsOptionsErr) throw clientsOptionsErr;
      if (productsErr) throw productsErr;
      if (profileErr) throw profileErr;
      if (domainErr && domainErr.code !== "PGRST116" && domainErr.code !== "42P01") throw domainErr;

      const resolvedItems = ((itemsData as ReviewItemRow[]) || []).map((item) => ({
        ...item,
        product_id: item.product_id || null,
        unit_cost: Number(item.unit_cost) || 0,
        selected_options: item.selected_options && typeof item.selected_options === "object" ? item.selected_options : null,
        valor_minimo_aplicado: item.valor_minimo_aplicado == null ? null : Number(item.valor_minimo_aplicado),
        valor_sem_minimo: item.valor_sem_minimo == null ? null : Number(item.valor_sem_minimo),
        unit_price_locked: false,
      }));
      const resolvedClient = (clientData as ReviewClientRow) || null;
      const resolvedClientsOptions = (clientsOptionsData as ReviewClientOption[]) || [];
      const resolvedProducts = (productsData as ReviewProductOption[]) || [];

      setReviewQuote(q);
      setReviewItems(resolvedItems);
      setReviewDraftItems(resolvedItems);
      setReviewClient(resolvedClient);
      setReviewClientOptions(resolvedClientsOptions);
      setReviewProducts(resolvedProducts);
      setReviewClientSearch("");
      setReviewDraftClientId(resolvedClient?.id || "");
      setReviewDraftWhatsApp(formatWhatsAppInput(resolvedClient?.whatsapp || ""));
      setReviewDraftNotes(q.notes || "");
      setReviewEditingClient(false);
      setReviewEditingNotes(false);
      setReviewEditingItemId(null);
      setReviewCreatingClient(false);
      setReviewNewClientName("");
      setReviewNewClientCompany("");
      setReviewNewClientWhatsApp("");
      const baseProfile = (profileData as ReviewProfileRow | null) || null;
      setReviewProfile(
        baseProfile
          ? {
              ...baseProfile,
              custom_domain: (domainData as { domain?: string | null } | null)?.domain || null,
              custom_domain_verified: Boolean((domainData as { verified?: boolean | null } | null)?.verified),
            }
          : null
      );
    } catch (err) {
      console.error("Erro ao carregar orçamento para revisão:", err);
      setReviewError("Falha ao carregar orçamento para revisão.");
    } finally {
      setReviewLoading(false);
    }
  }

  function closeReviewModal() {
    setIsReviewModalOpen(false);
    setReviewLoading(false);
    setReviewError("");
    setReviewQuote(null);
    setReviewItems([]);
    setReviewClient(null);
    setReviewClientOptions([]);
    setReviewClientSearch("");
    setReviewDraftClientId("");
    setReviewDraftWhatsApp("");
    setReviewDraftNotes("");
    setReviewDraftItems([]);
    setReviewProducts([]);
    setReviewEditingClient(false);
    setReviewEditingNotes(false);
    setReviewEditingDeliveryDate(false);
    setReviewEditingItemId(null);
    setReviewCreatingClient(false);
    setReviewNewClientName("");
    setReviewNewClientCompany("");
    setReviewNewClientWhatsApp("");
    setReviewSaving(false);
    setReviewProfile(null);
    setReviewApproved(false);
    setSharing(false);
    setCopied(false);
  }

  function patchReviewItem(
    itemId: string,
    patch: Partial<ReviewEditableItemRow>,
    options?: { manualPrice?: boolean; recalculatePrice?: boolean }
  ) {
    setReviewDraftItems((prev) =>
      prev.map((item) => {
        if (item.id !== itemId) return item;

        let next: ReviewEditableItemRow = { ...item, ...patch };
        // Preço digitado à mão não leva o mínimo do item.
        if (options?.manualPrice) next = { ...next, unit_price_locked: true, valor_minimo_aplicado: null, valor_sem_minimo: null };

        const shouldRecalculate =
          options?.recalculatePrice === true ||
          Object.prototype.hasOwnProperty.call(patch, "product_id") ||
          Object.prototype.hasOwnProperty.call(patch, "unit_type") ||
          Object.prototype.hasOwnProperty.call(patch, "quantity") ||
          Object.prototype.hasOwnProperty.call(patch, "width_m") ||
          Object.prototype.hasOwnProperty.call(patch, "height_m") ||
          Object.prototype.hasOwnProperty.call(patch, "length_m") ||
          Object.prototype.hasOwnProperty.call(patch, "selected_options");

        if (!next.product_id || next.unit_price_locked || !shouldRecalculate) return next;

        const product = reviewProductsById.get(next.product_id);
        if (!product) return next;

        return {
          ...next,
          unit_type: next.unit_type || product.unit_type || "unit",
          ...resolveReviewProductLine(next, product),
        };
      })
    );
  }

  function selectReviewProduct(itemId: string, productId: string) {
    const product = reviewProductsById.get(productId);
    if (!product) return;
    const minQty = getReviewMinimumItemQuantity(product);
    patchReviewItem(
      itemId,
      {
        product_id: product.id,
        title: product.name,
        description: product.description || "",
        quantity: minQty,
        unit_type: product.unit_type || "unit",
        width_m: product.unit_type === "square_meter" ? 1 : 0,
        height_m: product.unit_type === "square_meter" ? 1 : 0,
        length_m: product.unit_type === "linear_meter" || product.unit_type === "meter" ? 1 : 0,
        unit_cost: Number(product.cost_total) || 0,
        unit_price_locked: false,
        selected_options: null,
      },
      { recalculatePrice: true }
    );
  }

  function applyReviewProductMatch(itemId: string, value: string) {
    const normalized = value.trim().toLowerCase();
    const matched = reviewProducts.find((product) => product.name.trim().toLowerCase() === normalized);
    if (!matched) return;
    selectReviewProduct(itemId, matched.id);
  }

  function updateReviewItem(itemId: string, field: keyof ReviewEditableItemRow, value: string | number | null) {
    if (field === "quantity" || field === "unit_price" || field === "width_m" || field === "height_m" || field === "length_m") {
      patchReviewItem(itemId, { [field]: Number(value) || 0 } as Partial<ReviewEditableItemRow>);
      return;
    }
    patchReviewItem(itemId, { [field]: value } as Partial<ReviewEditableItemRow>);
  }

  function updateReviewItemMoney(itemId: string, value: string) {
    setReviewMoneyDrafts((prev) => ({ ...prev, [itemId]: formatMoneyInput(value) }));
    patchReviewItem(itemId, { unit_price: parseMoneyInput(value) }, { manualPrice: true });
  }

  function updateReviewItemMeasure(itemId: string, field: "width_m" | "height_m" | "length_m", value: string) {
    const formatted = formatMeasureInput(value);
    setReviewMeasureDrafts((prev) => ({
      ...prev,
      [itemId]: {
        width_m: prev[itemId]?.width_m || "",
        height_m: prev[itemId]?.height_m || "",
        length_m: prev[itemId]?.length_m || "",
        [field]: formatted,
      },
    }));
    patchReviewItem(itemId, { [field]: parseMeasureInput(formatted) } as Partial<ReviewEditableItemRow>);
  }

  function updateReviewItemAttribute(
    itemId: string,
    product: ReviewProductOption,
    attribute: ReviewProductAttributeValue,
    optionLabel: string
  ) {
    const item = reviewDraftItems.find((entry) => entry.id === itemId);
    if (!item) return;
    const currentMap = getReviewItemVariationMap(item);
    const currentValues = currentMap[attribute.name] || [];
    const allowMultiple = Boolean(attribute.allow_multiple);
    const nextValues = allowMultiple
      ? currentValues.includes(optionLabel)
        ? currentValues.filter((value) => value !== optionLabel)
        : [...currentValues, optionLabel]
      : [optionLabel];
    const nextMap = { ...currentMap, [attribute.name]: nextValues };
    const payload = buildReviewSelectedOptionsPayload(product, nextMap);
    patchReviewItem(itemId, { selected_options: payload }, { recalculatePrice: true });
  }

  function updateReviewWhatsApp(value: string) {
    setReviewDraftWhatsApp(formatWhatsAppInput(value));
  }

  function addReviewItem() {
    const tempId = `new:${Date.now()}:${Math.random().toString(36).slice(2, 7)}`;
    setReviewDraftItems((prev) => [
      ...prev,
      {
        id: tempId,
        tempKey: tempId,
        product_id: null,
        title: "",
        description: "",
        quantity: 1,
        unit_price: 0,
        unit_cost: 0,
        unit_type: "unit",
        width_m: null,
        height_m: null,
        length_m: null,
        line_total: 0,
        selected_options: null,
        unit_price_locked: false,
      },
    ]);
  }

  function removeReviewItem(itemId: string) {
    setReviewDraftItems((prev) => prev.filter((item) => item.id !== itemId));
  }

  function selectReviewClient(client: ReviewClientOption) {
    setReviewDraftClientId(client.id);
    setReviewDraftWhatsApp(formatWhatsAppInput(client.whatsapp || ""));
    setReviewClientSearch(client.company_name ? `${client.company_name} — ${client.name}` : client.name);
    setReviewEditingClient(false);
  }

  function handleReviewClientSelect(clientId: string) {
    if (!clientId) {
      setReviewDraftClientId("");
      setReviewEditingClient(false);
      return;
    }
    const client = reviewClientOptions.find((entry) => entry.id === clientId);
    if (client) selectReviewClient(client);
  }

  async function createReviewClientQuick() {
    const name = reviewNewClientName.trim();
    if (!name) {
      setReviewError("Informe o nome do cliente.");
      return;
    }

    setReviewSaving(true);
    setReviewError("");
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) throw new Error("Usuário não autenticado");
      const ctx = await getCompanyContext(supabase, user);
      const writeUserId = ctx.ownerId || user.id;

      const now = new Date().toISOString();
      const payload = {
        user_id: writeUserId,
        name,
        company_name: reviewNewClientCompany.trim() || null,
        whatsapp: normalizeDigits(reviewNewClientWhatsApp) || null,
        type: "pf",
        active: true,
        created_at: now,
        updated_at: now,
      };

      const { data, error } = await supabase
        .from("clients")
        .insert(payload)
        .select("id,name,company_name,whatsapp")
        .single();

      if (error) throw error;

      const newClient = data as ReviewClientOption;
      setReviewClientOptions((prev) => [newClient, ...prev]);
      setReviewDraftClientId(newClient.id);
      setReviewClient(newClient);
      setReviewClientSearch(newClient.company_name ? `${newClient.company_name} — ${newClient.name}` : newClient.name);
      setReviewDraftWhatsApp(formatWhatsAppInput(newClient.whatsapp || ""));
      setReviewCreatingClient(false);
      setReviewEditingClient(false);
      setReviewNewClientName("");
      setReviewNewClientCompany("");
      setReviewNewClientWhatsApp("");
    } catch (err) {
      console.error("Erro ao criar cliente rápido:", err);
      setReviewError("Não foi possível criar o cliente.");
    } finally {
      setReviewSaving(false);
    }
  }

  async function handleSaveReviewChanges(options?: { shareOnWhatsApp?: boolean; approveQuote?: boolean }) {
    if (!reviewQuote) return;

    // Se a intenção é só compartilhar e não há mudanças, não faz requisições ao banco, pula direto pro share.
    if (!hasChanges && !isDraftQuote && options?.shareOnWhatsApp && !options?.approveQuote) {
      if (reviewDraftWhatsApp) {
        window.setTimeout(() => {
          void handleWhatsAppShare();
        }, 300);
      }
      return;
    }

    if (reviewDraftItems.length === 0) {
      setReviewError("Adicione pelo menos um item antes de salvar.");
      return;
    }

    const cleanedItems = reviewDraftItems
      .map((item) => ({
        ...item,
        title: String(item.title || "").trim(),
        description: String(item.description || "").trim(),
        quantity: Math.max(0.001, Number(item.quantity) || 1),
        unit_price: Math.max(0, Number(item.unit_price) || 0),
        unit_cost: Math.max(0, Number(item.unit_cost) || 0),
        width_m: Number(item.width_m) || 0,
        height_m: Number(item.height_m) || 0,
        length_m: Number(item.length_m) || 0,
      }))
      .filter((item) => item.title);

    if (cleanedItems.length === 0) {
      setReviewError("Preencha ao menos um item com nome.");
      return;
    }

    setReviewSaving(true);
    setReviewError("");

    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) throw new Error("Usuário não autenticado");
      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];

      const selectedClient =
        reviewClientOptions.find((client) => client.id === reviewDraftClientId) ||
        reviewClient ||
        null;

      const nextClientId = selectedClient?.id || reviewQuote.client_id;
      if (!nextClientId || nextClientId === "draft") {
        setReviewError("Selecione um cliente para salvar o orçamento.");
        setReviewSaving(false);
        return;
      }
      
      const nextWhatsApp = normalizeDigits(reviewDraftWhatsApp);
      const subtotal = cleanedItems.reduce((sum, item) => sum + totalDaLinhaDaRevisao(item), 0);
      const total = Math.max(0, subtotal - (reviewQuote.discount || 0) + (reviewQuote.shipping || 0));

      let currentQuoteId = reviewQuote.id;
      const isDraft = currentQuoteId === "draft";

      if (isDraft) {
        const res = await fetch("/api/quotes", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({
            client_id: nextClientId || null,
            status: options?.approveQuote ? "approved" : "draft",
            title: reviewQuote.title || null,
            subtotal,
            discount: reviewQuote.discount || 0,
            shipping: reviewQuote.shipping || 0,
            total,
            expires_at: reviewQuote.expires_at || null,
            delivery_date: reviewDraftDeliveryDate || null,
            notes: reviewDraftNotes.trim() || null,
            items: cleanedItems,
          }),
        });

        const json = (await res.json().catch(() => null)) as { quoteId?: string; error?: string } | null;
        if (!res.ok || !json?.quoteId) {
          throw new Error(json?.error || "Erro ao criar orçamento.");
        }
        currentQuoteId = json.quoteId;

        // Atualizar o state com o novo ID (o modal vai recarregar ao final)
        setReviewQuote((prev) => prev ? { ...prev, id: currentQuoteId } : prev);
      } else {
        const { error: quoteUpdateError } = await supabase
          .from("quotes")
          .update({
            client_id: nextClientId,
            notes: reviewDraftNotes.trim() || null,
            delivery_date: reviewDraftDeliveryDate || null,
            subtotal,
            total,
            status: options?.approveQuote ? "approved" : reviewQuote.status,
            updated_at: new Date().toISOString(),
          })
          .eq("id", currentQuoteId)
          .in("user_id", tenantIds);

        if (quoteUpdateError) throw quoteUpdateError;
      }

      if (selectedClient?.id) {
        const { error: clientUpdateError } = await supabase
          .from("clients")
          .update({ whatsapp: nextWhatsApp || null, updated_at: new Date().toISOString() })
          .eq("id", selectedClient.id)
          .in("user_id", tenantIds);
        if (clientUpdateError) throw clientUpdateError;
      }

      const existingIds = new Set(reviewItems.map((item) => item.id));
      const updatedExistingIds = new Set<string>();

      if (!isDraft) {
        for (let index = 0; index < cleanedItems.length; index += 1) {
          const item = cleanedItems[index];
          const payload = {
            product_id: item.product_id || null,
            title: item.title,
            description: item.description || null,
            quantity: item.quantity,
            unit_price: item.unit_price,
            unit_cost: item.unit_cost || 0,
            unit_type: item.unit_type || "unit",
            width_m: item.width_m || 0,
            height_m: item.height_m || 0,
            length_m: item.length_m || 0,
            selected_options: item.selected_options || null,
            line_total: totalDaLinhaDaRevisao(item),
            valor_minimo_aplicado: item.unit_price_locked ? null : item.valor_minimo_aplicado ?? null,
            valor_sem_minimo: item.unit_price_locked || item.valor_minimo_aplicado == null ? null : item.valor_sem_minimo ?? null,
            position: index + 1,
          };

          if (existingIds.has(item.id)) {
            updatedExistingIds.add(item.id);
            const { error } = await supabase.from("quote_items").update(payload).eq("id", item.id).eq("quote_id", currentQuoteId);
            if (error) throw error;
          } else {
            const { error } = await supabase.from("quote_items").insert({
              quote_id: currentQuoteId,
              ...payload,
            });
            if (error) throw error;
          }
        }

        const removedIds = reviewItems.map((item) => item.id).filter((id) => !updatedExistingIds.has(id));
        if (removedIds.length > 0) {
          const { error } = await supabase.from("quote_items").delete().in("id", removedIds).eq("quote_id", currentQuoteId);
          if (error) throw error;
        }
      }

      setReviewQuote((prev) =>
        prev
          ? {
              ...prev,
              client_id: nextClientId,
              notes: reviewDraftNotes.trim() || null,
              subtotal,
              total,
              status: options?.approveQuote ? "approved" : prev.status,
            }
          : prev
      );

      const nextClientLabel = selectedClient
        ? {
            id: selectedClient.id,
            name: selectedClient.name,
            company_name: selectedClient.company_name,
            whatsapp: nextWhatsApp ? formatWhatsAppInput(nextWhatsApp) : null,
          }
        : reviewClient;
      setReviewClient(nextClientLabel);

      if (selectedClient) {
        setReviewClientOptions((prev) =>
          prev.map((item) => (item.id === selectedClient.id ? { ...item, whatsapp: nextWhatsApp || null } : item))
        );
      }

      await openReviewModal(currentQuoteId);

      if (options?.shareOnWhatsApp) {
        window.setTimeout(() => {
          void handleWhatsAppShare();
        }, 100);
      }
    } catch (err: any) {
      console.error("Erro ao salvar alterações inline:", err, err.message, err.details, err.hint, err.code);
      setReviewError("Não foi possível salvar as alterações do orçamento.");
    } finally {
      setReviewSaving(false);
    }
  }

  async function ensurePublicShare() {
    if (!reviewQuote) return null;
    if (reviewQuote.id === "draft") {
      setReviewError("Salve o orçamento primeiro para poder compartilhar o link.");
      return null;
    }
    const customDomain = String(reviewProfile?.custom_domain || "").trim().toLowerCase();
      const customDomainVerified = Boolean(reviewProfile?.custom_domain_verified);
      if (!reviewProfile?.slug && !(customDomain && customDomainVerified)) {
      setReviewError("Configure o link público da loja (slug) em Catálogo.");
      return null;
    }
    setSharing(true);
    setReviewError("");
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) throw new Error("Usuário não autenticado");

      let token = reviewQuote.share_token;
      if (!token) token = generateShareToken();
      /* O prazo configurado pela empresa, como na tela do orçamento e na
         lista: sem isso o link mandado daqui saía sem vencimento. */
      const prazo = prazoDoLink(reviewProfile?.quote_share_link_expires_enabled, reviewProfile?.quote_share_link_expires_days);

      const { error: upErr } = await supabase
        .from("quotes")
        .update({ share_enabled: true, share_token: token, share_expires_at: prazo })
        .eq("id", reviewQuote.id);

      if (upErr) {
        if ((upErr as { code?: string } | null)?.code === "23505") {
          token = generateShareToken();
          const { error: retryErr } = await supabase
            .from("quotes")
            .update({ share_enabled: true, share_token: token, share_expires_at: prazo })
            .eq("id", reviewQuote.id);
          if (retryErr) throw retryErr;
        } else {
          throw upErr;
        }
      }

      setReviewQuote((prev) => (prev ? { ...prev, share_enabled: true, share_token: token } : prev));
      const url =
        customDomain && customDomainVerified
          ? `https://${customDomain}/o/${token}`
          : `${publicBaseUrl}/${reviewProfile?.slug || ""}/o/${token}`;
      return { token, url };
    } catch (err) {
      console.error("Erro ao gerar link público:", err);
      setReviewError("Erro ao gerar link público.");
      return null;
    } finally {
      setSharing(false);
    }
  }

  async function handleCopyLink() {
    const share = await ensurePublicShare();
    if (!share) return;
    try {
      await navigator.clipboard.writeText(share.url);
      setCopied(true);
      window.setTimeout(() => setCopied(false), 1400);
      if (reviewQuote && reviewQuote.id !== "draft") void registrarEnvioDoLink(reviewQuote.id, "link");
    } catch (err) {
      console.error("Erro ao copiar:", err);
      setReviewError("Não foi possível copiar o link.");
    }
  }

  async function handleWhatsAppShare() {
    const share = await ensurePublicShare();
    if (!share || !reviewQuote) return;
    if (reviewQuote.id === "draft") {
      setReviewError("Salve o orçamento primeiro antes de enviar.");
      return;
    }
    const digits = normalizeDigits(reviewDraftWhatsApp || reviewClient?.whatsapp || "");
    if (!digits) {
      setReviewError("Cliente sem WhatsApp cadastrado.");
      return;
    }
    const templates = await fetchWhatsAppTemplates();
    const validade = reviewQuote.expires_at ? ` Validade: ${formatDateBr(reviewQuote.expires_at)}.` : "";
    /* Mesmo preenchimento da tela do orçamento: sem isto, uma mensagem com
       {{condicoes}} chegava ao cliente com o marcador cru. */
    const condicoes = normalizarCondicoes(reviewQuote.payment_terms);
    const message = resolveTemplate(
      templates.quote_share,
      "Olá! Segue o orçamento #{{numero_orcamento}}. Total: {{total}}.{{validade}}{{condicoes}} {{link}}",
      {
        numero_orcamento: String(reviewQuote.number),
        total: formatMoney(reviewQuote.total),
        validade,
        condicoes: condicoes ? ` Pagamento: ${resumirCondicoes(condicoes, reviewQuote.total)}` : "",
        link: share.url,
      }
    );
    window.open(`https://wa.me/${digits}?text=${encodeURIComponent(message)}`, "_blank", "noopener,noreferrer");
    void registrarEnvioDoLink(reviewQuote.id, "whatsapp");
  }

  function handleDownloadPdf() {
    if (!reviewQuote) return;
    if (reviewQuote.id === "draft") {
      setReviewError("Salve o orçamento primeiro antes de gerar o PDF.");
      return;
    }
    window.open(`/dashboard/quotes/${reviewQuote.id}?print=1`, "_blank", "noopener,noreferrer");
  }

  async function handleDeleteQuote() {
    if (!reviewQuote) return;
    if (reviewQuote.id === "draft") {
      closeReviewModal();
      return;
    }
    if (!confirm(`Excluir orçamento #${reviewQuote.number}?`)) return;
    try {
      const supabase = getSupabaseClient();
      const { error } = await supabase.from("quotes").delete().eq("id", reviewQuote.id);
      if (error) throw error;
      closeReviewModal();
    } catch (err) {
      console.error("Erro ao excluir orçamento:", err);
      setReviewError("Erro ao excluir orçamento.");
    }
  }

  async function handleCreateQuoteWithIA() {
    setIaCreating(true);
    setIaError("");
    try {
      const res = await fetch("/api/ia/criar-orcamento", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          instruction: iaOrcamentoText,
          imageDataUrl: iaOrcamentoImage,
        }),
      });
      const payload = (await res.json().catch(() => null)) as { draftPayload?: any; error?: string } | null;
      if (!res.ok) {
        setIaError(payload?.error || "Falha ao criar orçamento com IA.");
        return;
      }
      if (!payload?.draftPayload) {
        setIaError("Orçamento criado, mas sem dados de retorno.");
        return;
      }
      setIaOrcamentoText("");
      setIaOrcamentoImage(null);
      setIaOrcamentoImageName("");
      await openDraftReviewModal(payload.draftPayload);
    } catch (err) {
      console.error(err);
      setIaError("Falha ao criar orçamento com IA.");
    } finally {
      setIaCreating(false);
    }
  }

  function clearIaImage() {
    setIaOrcamentoImage(null);
    setIaOrcamentoImageName("");
  }

  function handleIaPaste(event: React.ClipboardEvent<HTMLTextAreaElement>) {
    const items = Array.from(event.clipboardData?.items || []);
    const imageItem = items.find((item) => item.type.startsWith("image/"));
    if (!imageItem) return;

    const file = imageItem.getAsFile();
    if (!file) return;
    event.preventDefault();

    const reader = new FileReader();
    reader.onload = () => {
      const result = typeof reader.result === "string" ? reader.result : "";
      if (!result) {
        setIaError("Não foi possível ler a imagem colada.");
        return;
      }
      setIaOrcamentoImage(result);
      setIaOrcamentoImageName(file.name || `print-${Date.now()}.png`);
      setIaError("");
    };
    reader.onerror = () => {
      setIaError("Falha ao carregar a imagem colada.");
    };
    reader.readAsDataURL(file);
  }

  const [bugModalOpen, setBugModalOpen] = useState(false);
  const [bugDescription, setBugDescription] = useState("");
  const [bugFlow, setBugFlow] = useState("");
  const [bugLocation, setBugLocation] = useState("");

  function handleOpenBugModal() {
    setBugModalOpen(true);
  }

  function handleSendBug() {
    const message = `*Relatório de Bug*\n\n*Descrição:* ${bugDescription}\n*Fluxo:* ${bugFlow}\n*Local:* ${bugLocation}`;
    const encoded = encodeURIComponent(message);
    window.open(`https://wa.me/5587988701216?text=${encoded}`, "_blank");
    setBugModalOpen(false);
    setBugDescription("");
    setBugFlow("");
    setBugLocation("");
  }

  function handleOpenGroup() {
    window.open("https://chat.whatsapp.com/DiKuv8OYc3EL3trGJWQUJX?mode=gi_t", "_blank");
  }

  return (
    <motion.div variants={container} initial="hidden" animate="show" className="space-y-6 pb-8">
      <PageHeader
        eyebrow="Visão geral"
        title={`Olá${userName ? `, ${userName}` : ""}`}
        subtitle="Acompanhe vendas, pedidos e orçamentos em tempo real."
        actions={
          <>
            <button
              type="button"
              onClick={handleOpenBugModal}
              className="ks-button ks-button-ghost"
            >
              <AlertCircle size={14} strokeWidth={1.75} />
              Informar bug
            </button>
            <button
              type="button"
              onClick={handleOpenGroup}
              className="ks-button ks-button-secondary"
            >
              <svg
                viewBox="0 0 24 24"
                className="w-3.5 h-3.5 fill-current"
                xmlns="http://www.w3.org/2000/svg"
              >
              <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.536 0 1.52 1.115 2.988 1.264 3.186.149.198 2.19 3.325 5.304 4.669.74.322 1.317.515 1.77.66.745.237 1.423.204 1.96.124.597-.086 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.96 1.002-3.645-.235-.383a9.872 9.872 0 01-1.512-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" />
              </svg>
              Grupo WhatsApp
            </button>
          </>
        }
      />

      {/* Bug Report Modal */}
      <Dialog open={bugModalOpen} onOpenChange={setBugModalOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Informar Bug</DialogTitle>
            <DialogDescription>
              Descreva o problema encontrado para que possamos corrigir.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-2">
            <div className="space-y-2">
              <label className="text-sm font-medium">Onde aconteceu?</label>
              <Input 
                placeholder="Ex: Tela de Orçamentos, Criação de Produto..." 
                value={bugLocation}
                onChange={e => setBugLocation(e.target.value)}
              />
            </div>
            <div className="space-y-2">
              <label className="text-sm font-medium">Descrição do problema</label>
              <textarea 
                className="w-full min-h-[80px] rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                placeholder="Ex: O botão de salvar não funciona..."
                value={bugDescription}
                onChange={e => setBugDescription(e.target.value)}
              />
            </div>
            <div className="space-y-2">
              <label className="text-sm font-medium">Fluxo (Passo a passo)</label>
              <textarea 
                className="w-full min-h-[80px] rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
                placeholder="Ex: 1. Cliquei em novo produto. 2. Preenchi o nome. 3. Cliquei em salvar."
                value={bugFlow}
                onChange={e => setBugFlow(e.target.value)}
              />
            </div>
          </div>
          <DialogFooter>
            <Button 
              onClick={handleSendBug} 
              disabled={!bugLocation.trim() || !bugDescription.trim() || !bugFlow.trim()}
              className="w-full bg-emerald-600 hover:bg-emerald-700 text-white gap-2 flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed"
              icon={<Send size={16} />}
            >
              Enviar no WhatsApp
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
        {stats.map((stat, idx) => {
          const isSensitive = Boolean(stat.sensitive);
          const isHidden = isSensitive && Boolean(hiddenStats[idx]);
          const tone = STAT_TONES[idx % STAT_TONES.length];

          return (
            <motion.div key={idx} variants={item} className={`ks-stat ${tone}`}>
              <span className="ks-stat-icon">
                <stat.icon size={26} strokeWidth={2} />
              </span>

              <div className="ks-stat-body">
                <p className="ks-stat-label">{stat.title}</p>
                <p className="ks-stat-value">
                  <AnimatedMetricValue
                    value={stat.rawValue}
                    format={stat.format}
                    hidden={isHidden}
                  />
                </p>
                <p className="ks-stat-foot">{stat.description}</p>
              </div>

              {isSensitive && (
                <button
                  type="button"
                  onClick={() => {
                    const next = { ...hiddenStats, [idx]: !hiddenStats[idx] };
                    setHiddenStats(next);
                    writeStoredJson("ks-hidden-stats", next);
                  }}
                  className="ks-stat-action self-start"
                  aria-label={isHidden ? "Mostrar valor" : "Ocultar valor"}
                >
                  {isHidden ? <EyeOff size={15} strokeWidth={2} /> : <Eye size={15} strokeWidth={2} />}
                </button>
              )}
            </motion.div>
          );
        })}
      </div>

      <motion.section variants={item}>
        <div className="mb-2.5 flex items-center justify-between gap-3">
          <h3 className="ks-section-title">Ações rápidas</h3>
          <button
            type="button"
            onClick={() => {
              setTempQuickActions(quickActions);
              setQuickActionsError("");
              setIsQuickActionsModalOpen(true);
            }}
            className="ks-button ks-button-ghost"
          >
            Editar
          </button>
        </div>
        <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6">
          {quickActions.map((actionId) => {
            const action = AVAILABLE_QUICK_ACTIONS.find(a => a.id === actionId);
            if (!action) return null;
            const Icon = action.icon;
            const tone = QUICK_ACTION_TONES[action.id] ?? "ks-tile-violet";
            return (
              <Link
                key={action.id}
                href={action.href}
                className="ks-card ks-card-hover flex flex-col items-start gap-3 p-4"
              >
                <span className={`ks-tile ks-tile-soft ${tone}`}>
                  <Icon size={21} strokeWidth={2} />
                </span>
                <span className="text-[13px] font-bold leading-tight text-[var(--ks-color-text-primary)]">
                  {action.label}
                </span>
              </Link>
            );
          })}
        </div>
      </motion.section>

      <div className="grid grid-cols-1 lg:grid-cols-12 gap-4 items-start">
        {podeVerIA && (
        <motion.section variants={item} className="ks-card lg:col-span-7">
          <div className="ks-card-head">
            <div className="flex min-w-0 items-center gap-3">
              <span className="ks-tile ks-tile-violet">
                <Sparkles size={21} strokeWidth={2} />
              </span>
              <div className="min-w-0">
                <h2 className="ks-section-title">Assistente de orçamentos</h2>
                <p className="ks-section-hint mt-0.5">
                  Cole a mensagem do cliente ou um print da conversa.
                </p>
              </div>
            </div>
          </div>

          <div className="ks-card-body">
            <div className="relative">
              <textarea
                value={iaOrcamentoText}
                onChange={(e) => setIaOrcamentoText(e.target.value)}
                onPaste={handleIaPaste}
                rows={5}
                className={`w-full resize-none rounded-[var(--ks-radius-md)] border-0 bg-[var(--ks-color-bg-inset)] px-4 py-3.5 text-[14px] leading-relaxed text-[var(--ks-color-text-primary)] outline-none transition-shadow placeholder:text-[var(--ks-color-text-soft)] focus:shadow-[var(--ks-focus-ring)] ${
                  iaOrcamentoImage ? "pb-20" : ""
                }`}
                placeholder="Cole a mensagem do WhatsApp do cliente, ou pressione Ctrl+V para colar um print da conversa…"
              />
              {iaOrcamentoImage ? (
                <div className="absolute bottom-2.5 left-2.5">
                  <div className="group relative inline-block h-12 w-12 overflow-hidden rounded-[var(--ks-radius-xs)] bg-[var(--ks-color-bg-elevated)] shadow-[var(--ks-shadow-subtle)]">
                    <img
                      src={iaOrcamentoImage}
                      alt="Print colado para leitura do orçamento"
                      className="h-full w-full object-cover"
                    />
                    <button
                      type="button"
                      onClick={clearIaImage}
                      className="absolute right-1 top-1 flex h-4 w-4 items-center justify-center rounded-full bg-black/65 text-white opacity-0 transition-opacity hover:bg-black/85 group-hover:opacity-100"
                      title="Remover imagem"
                    >
                      <X size={10} />
                    </button>
                  </div>
                </div>
              ) : null}
            </div>

            <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
              <p className="text-[13px] text-[var(--ks-color-text-muted)]">
                Criado como rascunho para você revisar antes de aprovar.
              </p>
              {/* A rota exige as duas: gerar com IA e criar o orçamento. */}
              {podeGerarComIA && podeMexerEmOrcamentos ? (
                <Button
                  type="button"
                  onClick={handleCreateQuoteWithIA}
                  disabled={iaCreating || (!iaOrcamentoText.trim() && !iaOrcamentoImage)}
                  icon={<Sparkles size={16} strokeWidth={2.2} />}
                >
                  {iaCreating ? "Processando…" : "Gerar rascunho"}
                </Button>
              ) : (
                <span className="text-[13px] text-[var(--ks-color-text-soft)]">
                  Você não tem permissão para gerar rascunhos.
                </span>
              )}
            </div>
            {iaError && (
              <p className="mt-2 text-[13px] text-[var(--ks-color-status-danger)]">{iaError}</p>
            )}
          </div>
        </motion.section>
        )}

        <motion.section variants={item} className="ks-card lg:col-span-5">
          <div className="ks-card-head">
            <div className="flex min-w-0 items-center gap-3">
              <span className="ks-tile ks-tile-soft ks-tile-emerald">
                <TrendingUp size={21} strokeWidth={2.2} />
              </span>
              <h3 className="ks-section-title">Receitas</h3>
            </div>
            <div className="relative" ref={rangeDropdownRef}>
              <button
                type="button"
                onClick={() => setIsRangeDropdownOpen(!isRangeDropdownOpen)}
                className="ks-button ks-button-soft ks-button-sm"
              >
                {rangeOptions.find((opt) => opt.value === range)?.label}
                <ChevronDown
                  size={13}
                  strokeWidth={2}
                  className={`text-[var(--ks-color-text-soft)] transition-transform ${isRangeDropdownOpen ? "rotate-180" : ""}`}
                />
              </button>

              <AnimatePresence>
                {isRangeDropdownOpen && (
                  <motion.div
                    initial={{ opacity: 0, y: -4 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: -4 }}
                    transition={{ duration: 0.12 }}
                    className="absolute right-0 top-full z-50 mt-2 w-40 overflow-hidden rounded-[var(--ks-radius-md)] bg-[var(--ks-color-bg-elevated)] p-1.5 shadow-[var(--ks-shadow-overlay)]"
                  >
                    {rangeOptions.map((opt) => (
                      <button
                        key={opt.value}
                        type="button"
                        onClick={() => {
                          setRange(opt.value);
                          setIsRangeDropdownOpen(false);
                        }}
                        className={`flex w-full items-center rounded-[var(--ks-radius-xs)] px-3 py-2 text-left text-[13px] transition-colors ${
                          range === opt.value
                            ? "bg-[var(--ks-brand-600)] font-bold text-white"
                            : "font-medium text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-brand-50)] hover:text-[var(--ks-brand-700)]"
                        }`}
                      >
                        {opt.label}
                      </button>
                    ))}
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
          </div>

          <div className="ks-card-body">
            <p className="ks-metric-label">Total do período</p>
            <p className="ks-metric-value mt-1">
              {formatMoney(chartData.points.reduce((sum, point) => sum + point.value, 0))}
            </p>

            <div className="mt-6">
              <RevenueChart
                points={chartData.points}
                maxValue={chartData.maxValue}
                formatValue={formatMoney}
                height={190}
              />
            </div>

            {chartData.points.length > 0 ? (
              <div className="mt-3 flex justify-between text-[11px] font-semibold tabular-nums text-[var(--ks-color-text-soft)]">
                <span>{chartData.points[0]?.label}</span>
                <span>{chartData.points[chartData.points.length - 1]?.label}</span>
              </div>
            ) : null}
          </div>
        </motion.section>
      </div>

      

      <motion.section variants={item}>
        <div className="mb-2.5 flex items-center justify-between gap-3">
          <h3 className="ks-section-title">Últimos pedidos</h3>
          <Link href="/dashboard/orders" className="ks-button ks-button-ghost">
            Ver todos
            <ChevronRight size={13} strokeWidth={2} />
          </Link>
        </div>

        {dashboardData.recentActivities.length === 0 ? (
          <div className="ks-card ks-empty-state">
            <p className="ks-empty-state-title">Nenhum pedido recente</p>
            <p className="ks-empty-state-subtitle">
              Os pedidos criados aparecem aqui assim que forem registrados.
            </p>
          </div>
        ) : (
          <div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
            {dashboardData.recentActivities.map((activity, idx) => (
              <Link
                key={activity.id}
                href={`/dashboard/orders/${activity.id}`}
                className="ks-card ks-card-hover group flex flex-col gap-3 p-5"
              >
                <div className="flex items-start justify-between gap-3">
                  <div className="min-w-0">
                    <p className="truncate text-[12px] font-medium text-[var(--ks-color-text-soft)]">
                      {activity.description}
                    </p>
                    <p className="mt-0.5 truncate text-[15px] font-bold text-[var(--ks-color-text-primary)]">
                      {activity.title}
                    </p>
                  </div>
                  <span className={`ks-tile ${ORDER_TONES[idx % ORDER_TONES.length]}`}>
                    <Package size={21} strokeWidth={2} />
                  </span>
                </div>

                <p className="text-[17px] font-extrabold tabular-nums text-[var(--ks-brand-600)]">
                  {formatMoney(activity.amount)}
                </p>

                <div className="mt-auto flex items-center justify-between gap-3 pt-1">
                  <span className={`ks-chip ${ORDER_STATUS_META[activity.status]?.chip ?? "ks-chip-neutral"}`}>
                    {ORDER_STATUS_META[activity.status]?.label ?? activity.status}
                  </span>
                  <span className="inline-flex items-center gap-1 text-[12px] font-semibold text-[var(--ks-color-text-soft)] transition-colors group-hover:text-[var(--ks-brand-600)]">
                    Ver pedido
                    <ChevronRight size={13} strokeWidth={2.4} />
                  </span>
                </div>
              </Link>
            ))}
          </div>
        )}
      </motion.section>

      <AnimatePresence>
        {isReviewModalOpen && (
          <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm p-4">
            <motion.div
              initial={{ opacity: 0, scale: 0.98, y: 8 }}
              animate={{ opacity: 1, scale: 1, y: 0 }}
              exit={{ opacity: 0, scale: 0.98, y: 8 }}
              className="w-full max-w-3xl flex flex-col overflow-hidden rounded-[20px] bg-white shadow-2xl max-h-full"
            >
              <div className="flex items-center justify-between px-6 py-5 border-b border-gray-100 bg-white relative overflow-hidden min-h-[88px]">
                {/* Ícone d'água no centro absoluto */}
                <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-gray-100/60 pointer-events-none rotate-[-15deg] mix-blend-multiply">
                  <Sparkles size={180} strokeWidth={1} />
                </div>
                
                <div className="flex flex-col relative z-10 w-1/3">
                  <h2 className="text-xl font-bold text-gray-900 tracking-tight">{quoteTitle}</h2>
                  <div className="flex items-center mt-0.5 min-h-[16px]">
                    <span className="text-xs font-bold text-gray-400 uppercase tracking-wider">
                      {reviewQuote?.status === "draft" && "Rascunho"}
                      {reviewQuote?.status === "sent" && "Enviado"}
                      {reviewQuote?.status === "approved" && "Aprovado"}
                      {reviewQuote?.status === "rejected" && "Rejeitado"}
                      {!reviewQuote?.status && "Rascunho"}
                    </span>
                  </div>
                </div>

                {/* Texto animado centralizado (Absoluto) */}
                {isDraftQuote && (
                  <div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center w-[300px] h-[30px] z-10 overflow-hidden">
                    <AnimatePresence mode="popLayout">
                      <motion.span
                        key={currentTextIndex}
                        initial={{ opacity: 0, y: 20 }}
                        animate={{ opacity: 1, y: 0 }}
                        exit={{ opacity: 0, y: -20 }}
                        transition={{ duration: 0.5, ease: "easeOut" }}
                        className="absolute text-xl font-bold text-gray-900 tracking-tight whitespace-nowrap"
                      >
                        {aiHeaderTexts[currentTextIndex]}
                      </motion.span>
                    </AnimatePresence>
                  </div>
                )}

                <div className="w-1/3 flex justify-end relative z-20">
                  <button
                    type="button"
                    onClick={closeReviewModal}
                    className="inline-flex h-8 w-8 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-700"
                    aria-label="Fechar"
                  >
                    <X size={16} />
                  </button>
                </div>
              </div>

              <div className="flex-1 overflow-auto p-6 sm:p-8">
                {reviewLoading ? (
                  <div className="py-10 text-center text-sm text-gray-500">Carregando...</div>
                ) : reviewQuote ? (
                  <div className="space-y-8">
                    <div className="grid grid-cols-1 gap-8 md:grid-cols-2">
                      <div>
                        <div className="flex items-center justify-between mb-3 border-b border-gray-100 pb-2">
                          <h3 className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Dados do Cliente</h3>
                          <button
                            type="button"
                            onClick={() => setReviewEditingClient((prev) => !prev)}
                            className="text-gray-400 hover:text-indigo-600 transition-colors"
                          >
                            <Pencil size={14} />
                          </button>
                        </div>
                        {reviewEditingClient ? (
                          <div className="space-y-3">
                            <CustomSelect
                              options={reviewClientSelectOptions}
                              value={reviewDraftClientId}
                              onChange={handleReviewClientSelect}
                              placeholder="Buscar cliente"
                              searchable
                              size="sm"
                              className="w-full"
                            />
                            <input
                              type="text"
                              value={reviewDraftWhatsApp}
                              onChange={(e) => updateReviewWhatsApp(e.target.value)}
                              placeholder="WhatsApp"
                              className="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                            />
                            <div className="flex justify-end">
                              <button
                                type="button"
                                onClick={() => {
                                  setReviewDraftClientId("");
                                  setReviewClientSearch("");
                                  setReviewEditingClient(false);
                                }}
                                className="text-xs font-semibold text-gray-500 hover:text-gray-700"
                              >
                                Sem cliente
                              </button>
                            </div>
                          </div>
                        ) : (
                          <div className="text-sm">
                            <p className="font-semibold text-gray-900">
                              {selectedReviewClient?.company_name || selectedReviewClient?.name || "Sem cliente"}
                            </p>
                            <p className="text-gray-500 mt-1">{reviewDraftWhatsApp || "WhatsApp não informado"}</p>
                          </div>
                        )}
                      </div>

                      <div>
                        <div className="flex items-center justify-between mb-3 border-b border-gray-100 pb-2">
                          <h3 className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Observações</h3>
                          <button
                            type="button"
                            onClick={() => setReviewEditingNotes((prev) => !prev)}
                            className="text-gray-400 hover:text-indigo-600 transition-colors"
                          >
                            <Pencil size={14} />
                          </button>
                        </div>
                        {reviewEditingNotes ? (
                          <textarea
                            value={reviewDraftNotes}
                            onChange={(e) => setReviewDraftNotes(e.target.value)}
                            rows={3}
                            className="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 resize-none"
                            placeholder="Observações do orçamento"
                          />
                        ) : (
                          <p className="text-sm text-gray-600 whitespace-pre-wrap">
                            {reviewDraftNotes || "Sem observações"}
                          </p>
                        )}
                      </div>
                    </div>

                    <div>
                      <div className="flex items-center justify-between mb-3">
                        <h3 className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Itens do Pedido</h3>
                        <button
                          type="button"
                          onClick={addReviewItem}
                          className="text-xs font-semibold text-indigo-600 hover:text-indigo-700"
                        >
                          + Adicionar item
                        </button>
                      </div>

                      <div className="rounded-xl border border-gray-200 overflow-hidden">
                        <div className="hidden sm:flex bg-gray-50/80 px-4 py-2 text-[10px] font-bold text-gray-500 uppercase tracking-wider border-b border-gray-200">
                          <div className="w-16">Qtd</div>
                          <div className="flex-1">Produto</div>
                          <div className="w-24 text-right">Unitário</div>
                          <div className="w-24 text-right">Total</div>
                          <div className="w-16"></div>
                        </div>

                        <div className="divide-y divide-gray-100">
                          {reviewDraftItems.length === 0 ? (
                            <div className="px-4 py-8 text-center text-sm text-gray-500">Nenhum item adicionado.</div>
                          ) : (
                            reviewDraftItems.map((it) => {
                              const isEditing = reviewEditingItemId === it.id;
                              const product =
                                (it.product_id ? reviewProductsById.get(it.product_id) || null : null) ||
                                reviewProducts.find((entry) => entry.name.trim().toLowerCase() === it.title.trim().toLowerCase()) ||
                                null;
                              const sugeriveis = reviewProducts.filter((p) => p.product_kind !== "digital");
                              const productMatches = it.title.trim()
                                ? sugeriveis
                                    .filter((p) => p.name.toLowerCase().includes(it.title.trim().toLowerCase()))
                                    .slice(0, 5)
                                : sugeriveis.slice(0, 5);
                              const selectedMap = getReviewItemVariationMap(it);
                              const selectedOptionsSummary = Object.entries(selectedMap)
                                .filter(([, labels]) => labels.length > 0)
                                .map(([attribute, labels]) => `${attribute}: ${labels.join(", ")}`)
                                .join(" / ");
                              const effectiveQty = effectiveReviewQuantity(it);
                              const totalDaLinha = totalDaLinhaDaRevisao(it);
                              const temMinimo = !it.unit_price_locked && it.valor_minimo_aplicado != null && Number(it.valor_minimo_aplicado) > 0;
                              const minQty = getReviewMinimumItemQuantity(product);
                              const allowedQuantities = getReviewAllowedQuantities(product);

                              return (
                                <div key={it.id} className="px-4 py-3 bg-white">
                                  {!isEditing ? (
                                    <div className="flex flex-col sm:flex-row sm:items-center gap-3">
                                      <div className="w-16 text-sm text-gray-600 font-medium hidden sm:block">
                                        {effectiveQty.toFixed(3).replace(/\.?0+$/, "")}
                                      </div>
                                      <div className="flex-1 min-w-0">
                                        <p className="text-sm font-semibold text-gray-900 truncate">
                                          {it.title || "Item sem nome"}
                                        </p>
                                        <p className="text-xs text-gray-500 sm:hidden mt-0.5">
                                          {effectiveQty.toFixed(3).replace(/\.?0+$/, "")} x {temMinimo ? "Valor mínimo" : formatMoney(it.unit_price)}
                                        </p>
                                        {temMinimo ? (
                                          <p className="text-[11px] text-sky-700 mt-0.5">
                                            {textoDoMinimoAplicado(it.valor_minimo_aplicado, it.valor_sem_minimo)}
                                          </p>
                                        ) : null}
                                        {it.description ? (
                                          <p className="text-xs text-gray-500 mt-0.5 truncate">{it.description}</p>
                                        ) : null}
                                        {selectedOptionsSummary ? (
                                          <p className="text-[11px] text-indigo-600 mt-0.5">{selectedOptionsSummary}</p>
                                        ) : null}
                                        {it.unit_type === "square_meter" ? (
                                          <p className="text-[11px] text-gray-400 mt-0.5">
                                            {`${Number(it.width_m) || 0}m x ${Number(it.height_m) || 0}m`}
                                          </p>
                                        ) : null}
                                        {it.unit_type === "linear_meter" || it.unit_type === "meter" ? (
                                          <p className="text-[11px] text-gray-400 mt-0.5">
                                            {`${Number(it.length_m) || 0}m`}
                                          </p>
                                        ) : null}
                                      </div>
                                      <div className="w-24 text-right text-sm text-gray-500 hidden sm:block">
                                        {temMinimo ? "Valor mínimo" : formatMoney(it.unit_price)}
                                      </div>
                                      <div className="w-24 text-right text-sm font-bold text-gray-900">
                                        {formatMoney(totalDaLinha)}
                                      </div>
                                      <div className="w-full sm:w-16 flex justify-end gap-2 mt-2 sm:mt-0">
                                        <button
                                          type="button"
                                          onClick={() => setReviewEditingItemId(it.id)}
                                          className="text-gray-400 hover:text-indigo-600 transition-colors p-1"
                                        >
                                          <Pencil size={14} />
                                        </button>
                                        <button
                                          type="button"
                                          onClick={() => removeReviewItem(it.id)}
                                          className="text-gray-400 hover:text-red-500 transition-colors p-1"
                                        >
                                          <Trash2 size={14} />
                                        </button>
                                      </div>
                                    </div>
                                  ) : (
                                    <div className="space-y-3 py-1">
                                      <div className="relative">
                                        <input
                                          list={`review-products-${it.id}`}
                                          type="text"
                                          value={it.title}
                                          onChange={(e) => updateReviewItem(it.id, "title", e.target.value)}
                                          onBlur={(e) => applyReviewProductMatch(it.id, e.target.value)}
                                          placeholder="Nome do produto"
                                          className="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-semibold outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                        />
                                        <datalist id={`review-products-${it.id}`}>
                                          {productMatches.map((p) => (
                                            <option key={p.id} value={p.name} />
                                          ))}
                                        </datalist>
                                        {productMatches.length > 0 ? (
                                          <div className="mt-2 flex flex-wrap gap-1.5">
                                            {productMatches.slice(0, 4).map((match) => (
                                              <button
                                                key={match.id}
                                                type="button"
                                                onClick={() => selectReviewProduct(it.id, match.id)}
                                                className={`rounded-md px-2 py-1 text-[10px] font-bold uppercase tracking-wider transition-colors ${
                                                  it.product_id === match.id
                                                    ? "bg-indigo-100 text-indigo-700"
                                                    : "bg-gray-100 text-gray-500 hover:bg-gray-200"
                                                }`}
                                              >
                                                {match.name}
                                              </button>
                                            ))}
                                          </div>
                                        ) : null}
                                      </div>

                                      <div className="flex flex-wrap gap-2">
                                        {allowedQuantities.length > 0 ? (
                                          <select
                                            value={String(it.quantity)}
                                            onChange={(e) => updateReviewItem(it.id, "quantity", e.target.value)}
                                            className="h-9 w-24 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                          >
                                            {allowedQuantities.map((value) => (
                                              <option key={value} value={value}>
                                                {value}
                                              </option>
                                            ))}
                                          </select>
                                        ) : (
                                          <input
                                            type="number"
                                            min={minQty}
                                            step="0.001"
                                            value={it.quantity}
                                            onChange={(e) => updateReviewItem(it.id, "quantity", e.target.value)}
                                            className="h-9 w-24 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                          />
                                        )}
                                        <input
                                          type="text"
                                          inputMode="decimal"
                                          value={reviewMoneyDrafts[it.id] ?? formatMoneyInput(Number(it.unit_price) || 0)}
                                          onChange={(e) => updateReviewItemMoney(it.id, e.target.value)}
                                          className="h-9 w-28 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                        />
                                        <div className="flex h-9 min-w-[100px] items-center justify-end rounded-lg bg-gray-50 px-3 text-sm font-bold text-gray-900 border border-gray-100">
                                          {formatMoney(totalDaLinha)}
                                        </div>
                                      </div>

                                      {it.unit_type === "square_meter" ? (
                                        <div className="flex flex-wrap gap-2">
                                          <input
                                            type="text"
                                            inputMode="decimal"
                                            value={reviewMeasureDrafts[it.id]?.width_m ?? formatMeasureInput(it.width_m)}
                                            onChange={(e) => updateReviewItemMeasure(it.id, "width_m", e.target.value)}
                                            placeholder="Largura (m)"
                                            className="h-9 w-24 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                          />
                                          <input
                                            type="text"
                                            inputMode="decimal"
                                            value={reviewMeasureDrafts[it.id]?.height_m ?? formatMeasureInput(it.height_m)}
                                            onChange={(e) => updateReviewItemMeasure(it.id, "height_m", e.target.value)}
                                            placeholder="Altura (m)"
                                            className="h-9 w-24 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                          />
                                        </div>
                                      ) : null}

                                      {it.unit_type === "linear_meter" || it.unit_type === "meter" ? (
                                        <input
                                          type="text"
                                          inputMode="decimal"
                                          value={reviewMeasureDrafts[it.id]?.length_m ?? formatMeasureInput(it.length_m)}
                                          onChange={(e) => updateReviewItemMeasure(it.id, "length_m", e.target.value)}
                                          placeholder="Comprimento (m)"
                                          className="h-9 w-32 rounded-lg border border-gray-200 bg-white px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                        />
                                      ) : null}

                                      {product && getSortedReviewAttributes(product).length > 0 ? (
                                        <div className="space-y-2 rounded-lg bg-gray-50 p-3 border border-gray-100">
                                          {getSortedReviewAttributes(product).map((attribute) => {
                                            const selectedLabels = selectedMap[attribute.name] || [];
                                            const normalizedOptions = (attribute.options || [])
                                              .map((option, index) => normalizeReviewAttributeOption(option, index))
                                              .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
                                            return (
                                              <div key={`${it.id}-${attribute.name}`} className="space-y-1">
                                                <p className="text-[10px] font-bold text-gray-500 uppercase tracking-wider">
                                                  {attribute.name}
                                                </p>
                                                <div className="flex flex-wrap gap-1.5">
                                                  {normalizedOptions.map((option) => {
                                                    const isSelected = selectedLabels.includes(option.label);
                                                    return (
                                                      <button
                                                        key={`${attribute.name}-${option.label}`}
                                                        type="button"
                                                        onClick={() =>
                                                          updateReviewItemAttribute(it.id, product, attribute, option.label)
                                                        }
                                                        className={`rounded-md px-2 py-1 text-xs font-medium transition-colors ${
                                                          isSelected
                                                            ? "bg-indigo-600 text-white"
                                                            : "bg-white border border-gray-200 text-gray-600 hover:bg-gray-100"
                                                        }`}
                                                      >
                                                        {option.label}
                                                      </button>
                                                    );
                                                  })}
                                                </div>
                                              </div>
                                            );
                                          })}
                                        </div>
                                      ) : null}

                                      <input
                                        type="text"
                                        value={it.description || ""}
                                        onChange={(e) => updateReviewItem(it.id, "description", e.target.value)}
                                        placeholder="Detalhes adicionais (opcional)"
                                        className="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                                      />
                                      
                                      <div className="flex justify-end pt-2">
                                        <button
                                          type="button"
                                          onClick={() => setReviewEditingItemId(null)}
                                          className="text-xs font-bold text-gray-500 uppercase tracking-wider hover:text-gray-900"
                                        >
                                          Concluir edição
                                        </button>
                                      </div>
                                    </div>
                                  )}
                                </div>
                              );
                            })
                          )}
                        </div>
                      </div>

                      <div className="flex justify-between items-start mt-6">
                        <div className="w-full sm:w-1/2 pr-4">
                          <div className="flex items-center gap-2 mb-2">
                            <h3 className="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Prazo de Entrega</h3>
                            <button
                              type="button"
                              onClick={() => setReviewEditingDeliveryDate((prev) => !prev)}
                              className="text-gray-400 hover:text-indigo-600 transition-colors"
                            >
                              <Pencil size={12} />
                            </button>
                          </div>
                          {reviewEditingDeliveryDate ? (
                            <input
                              type="date"
                              value={reviewDraftDeliveryDate}
                              onChange={(e) => {
                                setReviewDraftDeliveryDate(e.target.value);
                                if (e.target.value) setReviewEditingDeliveryDate(false);
                              }}
                              className="w-full max-w-[200px] rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
                            />
                          ) : (
                            <div 
                              className="text-sm text-gray-700 cursor-pointer hover:text-indigo-600 transition-colors inline-flex items-center gap-1"
                              onClick={() => setReviewEditingDeliveryDate(true)}
                            >
                              {reviewDraftDeliveryDate ? (
                                <>
                                  <Calendar size={14} className="text-indigo-500" />
                                  <span className="font-medium">{formatDateBr(reviewDraftDeliveryDate)}</span>
                                </>
                              ) : (
                                <span className="text-gray-400 italic">Definir prazo de entrega</span>
                              )}
                            </div>
                          )}
                        </div>

                        <div className="w-full sm:w-64 space-y-3 shrink-0">
                          <div className="flex justify-between text-sm">
                            <span className="text-gray-500 font-medium">Subtotal</span>
                            <span className="text-gray-900 font-semibold">{formatMoney(reviewDraftTotal)}</span>
                          </div>
                          <div className="flex justify-between text-lg border-t border-gray-900 pt-3">
                            <span className="text-gray-900 font-bold">Total</span>
                            <span className="text-gray-900 font-bold">{formatMoney(reviewDraftTotal)}</span>
                          </div>
                        </div>
                      </div>
                    </div>

                    {reviewError ? <p className="text-sm text-red-600 font-medium">{reviewError}</p> : null}
                  </div>
                ) : (
                  <>
                    {reviewError ? <p className="text-sm text-red-600 font-medium">{reviewError}</p> : null}
                    <div className="py-10 text-center text-sm text-gray-500">Orçamento não disponível.</div>
                  </>
                )}
              </div>

              <div className="border-t border-gray-100 bg-gray-50/80 p-4 sm:px-6 flex flex-col-reverse sm:flex-row sm:items-center justify-between gap-3">
                {podeMexerEmOrcamentos && (<Button
                  type="button"
                  onClick={handleDeleteQuote}
                  disabled={!reviewQuote}
                  variant="ghost"
                  className="text-gray-500 hover:text-red-600 hover:bg-red-50 w-full sm:w-auto"
                  icon={<Trash2 size={14} />}
                >
                  Excluir
                </Button>)}
                <div className="flex flex-col sm:flex-row items-center gap-2 w-full sm:w-auto">
                  <Button
                    type="button"
                    onClick={() => {
                      if (!reviewQuote) return;
                      closeReviewModal();
                      router.push(`/dashboard/quotes/${reviewQuote.id}`);
                    }}
                    disabled={reviewLoading || !reviewQuote}
                    className="w-full sm:w-auto h-10 rounded-lg border border-gray-200 bg-white px-4 text-xs font-bold text-gray-600 transition hover:bg-gray-50 flex items-center justify-center gap-1.5 whitespace-nowrap"
                    icon={<ExternalLink size={14} />}
                  >
                    Abrir Completo
                  </Button>
                  <Button
                    type="button"
                    onClick={handleCopyLink}
                    disabled={sharing || !reviewQuote}
                    className="w-full sm:w-auto h-10 rounded-lg border border-gray-200 bg-white px-4 text-xs font-bold text-gray-600 transition hover:bg-gray-50 flex items-center justify-center gap-1.5 whitespace-nowrap"
                    icon={copied ? <Check size={14} className="text-emerald-500" /> : <Copy size={14} />}
                  >
                    {copied ? "Copiado" : "Copiar link"}
                  </Button>
                  {podeMexerNoCatalogo && (<Button
                    type="button"
                    onClick={() => void handleSaveReviewChanges()}
                    disabled={reviewLoading || !reviewQuote || reviewSaving || (!hasChanges && !isDraftQuote)}
                    className="w-full sm:w-auto h-10 rounded-lg bg-indigo-50 px-4 text-xs font-bold text-indigo-700 transition hover:bg-indigo-100 flex items-center justify-center gap-1.5 whitespace-nowrap disabled:opacity-50"
                    icon={<Save size={14} />}
                  >
                    Salvar
                  </Button>)}
                  <Button
                    type="button"
                    onClick={() => void handleSaveReviewChanges({ shareOnWhatsApp: true })}
                    disabled={reviewLoading || !reviewQuote || reviewSaving || !reviewDraftWhatsApp.trim()}
                    className="w-full sm:w-auto h-10 rounded-lg !bg-gradient-to-r !from-[#25D366] !to-[#128C7E] hover:!brightness-105 active:!brightness-95 !text-white !border-none px-4 text-xs font-bold flex items-center justify-center gap-1.5 whitespace-nowrap shadow-none disabled:opacity-50"
                    icon={<WhatsAppIcon className="w-4 h-4" />}
                  >
                    {reviewSaving ? "Salvando..." : (!hasChanges && !isDraftQuote ? "Enviar" : "Salvar e enviar")}
                  </Button>
                </div>
              </div>
            </motion.div>
          </div>
        )}
      </AnimatePresence>

      <Dialog open={isQuickActionsModalOpen} onOpenChange={setIsQuickActionsModalOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Editar Ações Rápidas</DialogTitle>
            <DialogDescription>
              Selecione quais ações você deseja exibir no painel principal.
            </DialogDescription>
          </DialogHeader>
          <div className="py-4 space-y-3">
            {AVAILABLE_QUICK_ACTIONS.map((action) => {
              const isSelected = tempQuickActions.includes(action.id);
              const Icon = action.icon;
              return (
                <div key={action.id} className="flex cursor-pointer items-center justify-between rounded-[var(--ks-radius-sm)] bg-[var(--ks-color-bg-inset)] p-3 transition-colors hover:bg-[var(--ks-brand-50)]" onClick={() => {
                  if (isSelected) {
                    setTempQuickActions(tempQuickActions.filter(id => id !== action.id));
                  } else {
                    setTempQuickActions([...tempQuickActions, action.id]);
                  }
                }}>
                  <div className="flex items-center gap-3">
                    <span className={`ks-tile ks-tile-soft ${QUICK_ACTION_TONES[action.id] ?? "ks-tile-violet"} ks-tile-sm`}>
                      <Icon size={17} strokeWidth={2} />
                    </span>
                    <span className="text-sm font-bold text-[var(--ks-color-text-primary)]">{action.label}</span>
                  </div>
                  <div
                    className={`flex h-5 w-5 items-center justify-center rounded-full transition-colors ${
                      isSelected
                        ? "bg-[var(--ks-brand-600)]"
                        : "border-2 border-[var(--ks-color-border-strong)]"
                    }`}
                  >
                    {isSelected && <Check size={12} strokeWidth={3} className="text-white" />}
                  </div>
                </div>
              );
            })}
          </div>
          {quickActionsError ? (
            <p className="rounded-[var(--ks-radius-sm)] bg-[var(--ks-color-status-danger-soft)] px-3 py-2 text-[13px] font-medium text-[var(--ks-color-status-danger)]">
              {quickActionsError}
            </p>
          ) : null}
          <DialogFooter>
            <Button variant="outline" onClick={() => setIsQuickActionsModalOpen(false)}>Cancelar</Button>
            <Button onClick={() => {
              if (!writeStoredJson(quickActionsKey(userId), tempQuickActions)) {
                setQuickActionsError(
                  "Não foi possível salvar neste navegador. Verifique se os dados de site estão bloqueados ou se você está numa janela anônima."
                );
                return;
              }
              setQuickActions(tempQuickActions);
              setQuickActionsError("");
              setIsQuickActionsModalOpen(false);
            }}>
              Salvar
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

    </motion.div>
  );
}
