"use client";

import { useEffect, useMemo, useRef, useState, type PointerEvent, type ReactNode } from "react";
import type { RealtimeChannel } from "@supabase/supabase-js";
import { Check, CheckCircle2, Clock, FileDown, FileText, Image as ImageIcon, Loader2, PackageCheck, PackageSearch, X, XCircle } from "lucide-react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { getSupabaseClient } from "@/lib/supabase";
import { leituraDoOrcamento } from "@/lib/leitura-do-orcamento";

type PublicQuoteActionsProps = {
  token: string;
  quoteId: string;
  /* Link de acompanhamento do pedido, quando ele já existe. */
  statusLink?: string | null;
  quoteNumber: number;
  notificationTargetId: string;
  orderNumber?: number | null;
  currency: string;
  total: number;
  status?: string | null;
  logoUrl?: string | null;
  hideTotalInPublic?: boolean;
  pendingArtsCount: number;
  hasArts: boolean;
  allArtsApproved: boolean;
  requireSignature: boolean;
  artApprovalRequired: boolean;
};

type ApprovePublicQuoteResult = {
  order_id: string;
  order_number: number;
};

type PublicQuoteArtMessage = {
  id: string;
  sender: "client" | "company";
  message: string;
  status?: string | null;
  created_at?: string | null;
  delivered_at?: string | null;
  read_at?: string | null;
};

type PublicQuoteArt = {
  id: string;
  quote_item_id: string;
  title: string | null;
  notes: string | null;
  image_urls: string[];
  approval_status?: string | null;
  approval_notes?: string | null;
  approved_at?: string | null;
  reviewed_at?: string | null;
  messages?: PublicQuoteArtMessage[];
};

type PublicQuoteArtGroup = {
  itemId: string;
  itemIndex: number;
  itemTitle: string | null;
  itemDescription: string | null;
  arts: PublicQuoteArt[];
};

export default function PublicQuoteActions({
  token,
  quoteId,
  quoteNumber,
  notificationTargetId,
  orderNumber,
  currency,
  total,
  status,
  logoUrl,
  hideTotalInPublic = false,
  pendingArtsCount,
  hasArts,
  allArtsApproved,
  requireSignature,
  artApprovalRequired,
  statusLink = null,
}: PublicQuoteActionsProps) {
  const router = useRouter();
  const [modalOpen, setModalOpen] = useState(false);
  const [step, setStep] = useState<"confirm" | "processing" | "done">("confirm");
  const [error, setError] = useState("");
  const [approvedOrder, setApprovedOrder] = useState<{ id: string; number: number } | null>(null);
  const [approving, setApproving] = useState(false);
  const [approved, setApproved] = useState(status === "approved");
  /* Orçamento recusado pela loja não vira pedido pelo link (o banco recusa
     desde a migration 161). A tela avisa em vez de oferecer o botão. */
  const recusadoPelaLoja = status === "rejected";
  const [signatureName, setSignatureName] = useState("");
  const [signatureDataUrl, setSignatureDataUrl] = useState("");
  const [signatureError, setSignatureError] = useState("");
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const drawing = useRef(false);
  const displayOrderNumber = approvedOrder?.number ?? orderNumber ?? null;
  const printInProgress = useRef(false);
  const notificationChannelRef = useRef<RealtimeChannel | null>(null);

  /* A leitura do orçamento: quem abriu, por quanto tempo leu e o que clicou.
     É ela que conta a visualização do painel agora, pela mesma função do
     banco de antes (lib/leitura-do-orcamento.ts). */
  useEffect(() => {
    leituraDoOrcamento(token);
  }, [token]);

  useEffect(() => {
    const handleAfterPrint = () => {
      printInProgress.current = false;
    };
    window.addEventListener("afterprint", handleAfterPrint);
    return () => {
      window.removeEventListener("afterprint", handleAfterPrint);
    };
  }, []);

  useEffect(() => {
    const supabase = getSupabaseClient();
    const channel = supabase.channel("admin-notifications");
    channel.subscribe();
    notificationChannelRef.current = channel;
    return () => {
      supabase.removeChannel(channel);
      notificationChannelRef.current = null;
    };
  }, []);

  const notifyAdmin = async (payload: {
    id: string;
    quote_id: string;
    art_id: string | null;
    message: string;
    created_at: string;
    kind: "quote_approved";
    quote_number: number;
    target_user_id?: string;
  }) => {
    if (!notificationChannelRef.current) return;
    await notificationChannelRef.current.send({
      type: "broadcast",
      event: "client_message",
      payload,
    });
  };

  useEffect(() => {
    const root = document.documentElement;
    if (approved || approvedOrder) {
      root.setAttribute("data-quote-approved", "true");
    } else {
      root.removeAttribute("data-quote-approved");
    }
    const labelText = hideTotalInPublic ? "LISTA DE PREÇOS" : approved || approvedOrder ? "PEDIDO" : "ORÇAMENTO";
    document.querySelectorAll("[data-quote-type-target]").forEach((el) => {
      el.textContent = labelText;
    });
    if (displayOrderNumber) {
      const numberText = `#${displayOrderNumber}`;
      document.querySelectorAll("[data-order-number-target]").forEach((el) => {
        el.textContent = numberText;
      });
      document.querySelectorAll("[data-order-service-number]").forEach((el) => {
        el.textContent = String(displayOrderNumber);
      });
    }
  }, [approved, approvedOrder, displayOrderNumber, hideTotalInPublic]);

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

  useEffect(() => {
    if (!modalOpen || step !== "confirm") return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const parent = canvas.parentElement;
    if (!parent) return;
    const width = parent.clientWidth;
    const height = 160;
    const ratio = window.devicePixelRatio || 1;
    canvas.width = Math.max(1, Math.floor(width * ratio));
    canvas.height = Math.max(1, Math.floor(height * ratio));
    canvas.style.width = `${width}px`;
    canvas.style.height = `${height}px`;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
    ctx.lineCap = "round";
    ctx.strokeStyle = "#111827";
    ctx.lineWidth = 2;
    ctx.clearRect(0, 0, width, height);
    if (signatureDataUrl) {
      const img = new window.Image();
      img.onload = () => {
        ctx.drawImage(img, 0, 0, width, height);
      };
      img.src = signatureDataUrl;
    }
  }, [modalOpen, step, signatureDataUrl]);

  function getCanvasPoint(event: PointerEvent<HTMLCanvasElement>) {
    const canvas = canvasRef.current;
    if (!canvas) return { x: 0, y: 0 };
    const rect = canvas.getBoundingClientRect();
    return {
      x: event.clientX - rect.left,
      y: event.clientY - rect.top,
    };
  }

  function startDrawing(event: PointerEvent<HTMLCanvasElement>) {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    canvas.setPointerCapture(event.pointerId);
    drawing.current = true;
    const point = getCanvasPoint(event);
    ctx.beginPath();
    ctx.moveTo(point.x, point.y);
  }

  function draw(event: PointerEvent<HTMLCanvasElement>) {
    if (!drawing.current) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    const point = getCanvasPoint(event);
    ctx.lineTo(point.x, point.y);
    ctx.stroke();
  }

  function stopDrawing(event: PointerEvent<HTMLCanvasElement>) {
    if (!drawing.current) return;
    drawing.current = false;
    const canvas = canvasRef.current;
    if (!canvas) return;
    canvas.releasePointerCapture(event.pointerId);
    setSignatureDataUrl(canvas.toDataURL("image/png"));
    setSignatureError("");
  }

  function clearSignature() {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    setSignatureDataUrl("");
  }

  function handleDownloadPdf() {
    if (printInProgress.current) return;
    printInProgress.current = true;
    leituraDoOrcamento(token).acao("pdf");
    if (!logoUrl) {
      window.print();
      window.setTimeout(() => {
        printInProgress.current = false;
      }, 5000);
      return;
    }
    const img = new window.Image();
    let completed = false;
    const finish = () => {
      if (completed) return;
      completed = true;
      window.print();
      window.setTimeout(() => {
        printInProgress.current = false;
      }, 5000);
    };
    img.onload = finish;
    img.onerror = finish;
    img.src = logoUrl;
    window.setTimeout(finish, 4000);
  }

  function openModal() {
    setError("");
    setSignatureError("");
    setStep("confirm");
    setModalOpen(true);
    leituraDoOrcamento(token).acao("aprovar");
  }

  function closeModal() {
    if (approving) return;
    setModalOpen(false);
  }

  async function handleApprove() {
    if (approving) return;
    setError("");
    setSignatureError("");
    if (artApprovalRequired && !allArtsApproved) {
      setError("Existem artes pendentes de aprovação.");
      return;
    }
    if (requireSignature && !signatureDataUrl) {
      setSignatureError("Assine para continuar.");
      return;
    }
    setApproving(true);
    setStep("processing");
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      const signaturePayload = signatureDataUrl || null;
      let { data, error } = await supabase.rpc("approve_public_quote_and_generate_order", {
        p_token: token,
        p_signature: signaturePayload,
        p_signed_name: signatureName || null,
      });
      if (error && error.code === "PGRST202") {
        if (user) {
          const fallback = await supabase.rpc("approve_quote_and_generate_order", {
            p_quote_id: quoteId,
            p_signature: signaturePayload,
            p_signed_name: signatureName || null,
          });
          data = fallback.data;
          error = fallback.error;
        } else {
          throw new Error(
            "Função pública de aprovação não está disponível. Execute o SQL apps/admin/update_schema.sql no Supabase."
          );
        }
      }
      if (error) throw error;
      const payload = data as ApprovePublicQuoteResult | null;
      if (!payload?.order_id || !payload?.order_number) {
        throw new Error("Resposta inválida ao aprovar orçamento.");
      }
      const now = new Date().toISOString();
      const notificationId = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `quote-${quoteId}-${Date.now()}`;
      await notifyAdmin({
        id: notificationId,
        quote_id: quoteId,
        art_id: null,
        message: `Orçamento aprovado online. Pedido #${payload.order_number}.`,
        created_at: now,
        kind: "quote_approved",
        quote_number: quoteNumber,
        target_user_id: notificationTargetId,
      });
      setApprovedOrder({ id: payload.order_id, number: payload.order_number });
      setApproved(true);
      setStep("done");
      leituraDoOrcamento(token).acao("aprovou");
      router.refresh();
    } catch (err) {
      const baseMessage =
        typeof err === "object" && err && "message" in err && typeof err.message === "string"
          ? err.message
          : "Não foi possível aprovar o orçamento. Tente novamente.";
      const details =
        typeof err === "object" && err && "details" in err && typeof err.details === "string"
          ? err.details
          : "";
      const hint =
        typeof err === "object" && err && "hint" in err && typeof err.hint === "string"
          ? err.hint
          : "";
      const code =
        typeof err === "object" && err && "code" in err && typeof err.code === "string"
          ? err.code
          : "";
      /* Falta de estoque (trava do banco, v2 ou regra antiga): o cliente vê
         uma frase dele, sem código, sem JSON e sem o nome do insumo. A loja
         vê o detalhe no painel. */
      const faltouEstoque =
        hint.startsWith("ESTOQUE_") || /estoque insuficiente|sem estoque|opcao de estoque nao encontrada/i.test(baseMessage);
      const message = faltouEstoque
        ? "Não deu para aprovar agora: um item deste orçamento está sem estoque no momento. Fale com a loja para ajustar o orçamento."
        : [baseMessage, details, hint, code ? `(code: ${code})` : ""].filter(Boolean).join(" ");
      setError(message);
      setStep("confirm");
    } finally {
      setApproving(false);
    }
  }

  const commitmentText =
    "Ao aprovar este orçamento, você confirma a intenção de contratação e concorda que ele passa a ter compromisso comercial, podendo gerar obrigações de pagamento e início da produção, conforme os princípios do Código Civil e do Código de Defesa do Consumidor aplicáveis.";

  return (
    <div className="print-hidden space-y-4">
      {(approved || approvedOrder) && (
        <div className="rounded-2xl border-2 border-emerald-500 bg-emerald-50 px-6 py-5">
          <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
            <div className="flex items-start gap-3">
              <div className="mt-0.5 flex h-10 w-10 items-center justify-center rounded-full bg-emerald-600 text-white">
                <Check size={20} />
              </div>
              <div>
                <div className="text-lg font-extrabold text-emerald-800">
                  Esse orçamento foi aprovado
                </div>
                {displayOrderNumber ? (
                  <div className="text-sm font-semibold text-emerald-700">
                    Ordem de Serviço Nº {displayOrderNumber}
                  </div>
                ) : (
                  <div className="text-sm font-semibold text-emerald-700">
                    Ordem de Serviço gerada
                  </div>
                )}
              </div>
            </div>
            {displayOrderNumber && (
              <div className="text-sm font-semibold text-emerald-700">
                Pedido #{displayOrderNumber}
              </div>
            )}
          </div>
        </div>
      )}

      <div className="rounded-2xl border border-zinc-200 bg-white p-5 shadow-sm">
        <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
          <div className="space-y-1">
            <div className="text-sm font-semibold text-zinc-900">
              {hideTotalInPublic ? "Ações da lista de preços" : "Ações do orçamento"}
            </div>
            <div className="text-sm text-zinc-600">
              {hideTotalInPublic ? `Orçamento #${quoteNumber}` : `Orçamento #${quoteNumber} • Total ${formatMoney(total)}`}
            </div>
            {displayOrderNumber ? (
              <div className="inline-flex items-center gap-2 text-xs font-semibold text-emerald-700">
                <Check size={14} />
                Pedido #{displayOrderNumber} gerado
              </div>
            ) : approved ? (
              <div className="inline-flex items-center gap-2 text-xs font-semibold text-emerald-700">
                <Check size={14} />
                Orçamento aprovado
              </div>
            ) : recusadoPelaLoja ? (
              <div className="inline-flex items-center gap-2 text-xs font-semibold text-rose-700">
                Orçamento recusado. Fale com a loja para reabrir.
              </div>
            ) : artApprovalRequired && hasArts && pendingArtsCount > 0 ? (
              <div className="inline-flex items-center gap-2 text-xs font-semibold text-amber-700">
                <PackageCheck size={14} />
                {pendingArtsCount} arte(s) pendente(s) de aprovação
              </div>
            ) : null}
          </div>

          <div className="flex flex-col sm:flex-row gap-3">
            <button
              type="button"
              onClick={handleDownloadPdf}
              className="inline-flex items-center justify-center gap-2 rounded-xl border border-zinc-200 bg-white px-5 py-3 text-sm font-semibold text-zinc-800 shadow-sm transition hover:bg-zinc-100"
            >
              <FileDown size={18} />
              Baixar PDF
            </button>
            {!hideTotalInPublic && !(recusadoPelaLoja && !approved && !displayOrderNumber) ? (
              <button
                type="button"
                onClick={openModal}
                disabled={approved || approving}
                className="inline-flex items-center justify-center gap-2 rounded-xl bg-emerald-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-emerald-200 transition hover:bg-emerald-700 disabled:cursor-not-allowed disabled:bg-emerald-300"
              >
                <PackageCheck size={18} />
                Aprovar orçamento
              </button>
            ) : null}
          </div>
        </div>
      </div>

      {modalOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="absolute inset-0 bg-black/50 backdrop-blur-[2px]" onClick={closeModal} />
          <div className="relative w-full max-w-xl overflow-hidden rounded-2xl bg-white shadow-2xl">
            <div className="border-b border-zinc-100 bg-zinc-50 px-6 py-4">
              <div className="text-lg font-semibold text-zinc-900">Aprovar orçamento</div>
              <div className="text-xs text-zinc-500">Confirme os dados antes de continuar</div>
            </div>
            <div className="p-6">
            <button
              type="button"
              onClick={closeModal}
              className="absolute right-4 top-4 rounded-full p-2 text-zinc-500 transition hover:bg-zinc-100"
              aria-label="Fechar"
            >
              <X size={16} />
            </button>

            {step === "confirm" && (
              <div className="space-y-4">
                <div className="flex items-start gap-3 rounded-xl border border-emerald-100 bg-emerald-50 p-4 text-emerald-800">
                  <PackageCheck size={20} />
                  <div>
                    <div className="text-sm font-semibold">Você está prestes a aprovar</div>
                    <div className="text-xs text-emerald-700">
                      {hideTotalInPublic ? `Orçamento #${quoteNumber}` : `Orçamento #${quoteNumber} • Total ${formatMoney(total)}`}
                    </div>
                  </div>
                </div>
                {artApprovalRequired && pendingArtsCount > 0 && (
                  <div className="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800">
                    Existem {pendingArtsCount} artes pendentes de aprovação. Revise antes de aprovar o orçamento.
                  </div>
                )}
                <p className="text-sm text-zinc-600">{commitmentText}</p>
                {requireSignature && (
                  <div>
                    <div className="text-sm font-semibold text-zinc-900">Assinatura do cliente</div>
                    <div className="mt-2 rounded-xl border border-zinc-200 bg-white p-3">
                      <canvas
                        ref={canvasRef}
                        className="h-40 w-full touch-none"
                        onPointerDown={startDrawing}
                        onPointerMove={draw}
                        onPointerUp={stopDrawing}
                        onPointerLeave={stopDrawing}
                      />
                    </div>
                    <div className="mt-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                      <input
                        value={signatureName}
                        onChange={(event) => setSignatureName(event.target.value)}
                        className="w-full rounded-xl border border-zinc-200 px-3 py-2 text-sm text-zinc-700 focus:border-emerald-400 focus:outline-none"
                        placeholder="Nome do responsável (opcional)"
                      />
                      <button
                        type="button"
                        onClick={clearSignature}
                        className="inline-flex items-center justify-center rounded-xl border border-zinc-200 px-4 py-2 text-xs font-semibold text-zinc-700 transition hover:bg-zinc-100"
                      >
                        Limpar assinatura
                      </button>
                    </div>
                    {signatureError && <div className="mt-2 text-xs text-rose-600">{signatureError}</div>}
                  </div>
                )}
                {error && <div className="text-sm text-red-600">{error}</div>}
                <div className="flex flex-col sm:flex-row gap-2">
                  <button
                    type="button"
                    onClick={handleApprove}
                    className="inline-flex items-center justify-center gap-2 rounded-xl bg-emerald-600 px-5 py-2.5 text-sm font-semibold text-white shadow-lg shadow-emerald-200 transition hover:bg-emerald-700 disabled:cursor-not-allowed disabled:bg-emerald-300"
                    disabled={(artApprovalRequired && !allArtsApproved) || approving}
                  >
                    <PackageCheck size={16} />
                    Confirmar aprovação
                  </button>
                  <button
                    type="button"
                    onClick={closeModal}
                    className="inline-flex items-center justify-center gap-2 rounded-xl border border-zinc-200 bg-white px-5 py-2.5 text-sm font-semibold text-zinc-700 transition hover:bg-zinc-100"
                  >
                    Cancelar
                  </button>
                </div>
              </div>
            )}

            {step === "processing" && (
              <div className="space-y-4">
                <div className="text-lg font-semibold text-zinc-900">Obrigado pela aprovação!</div>
                <div className="text-sm text-zinc-600">
                  Gerando pedido... Isso leva apenas alguns instantes.
                </div>
                <div className="h-2 w-full overflow-hidden rounded-full bg-zinc-100">
                  <div className="h-full w-full animate-pulse rounded-full bg-emerald-500" />
                </div>
                <div className="inline-flex items-center gap-2 text-sm text-zinc-600">
                  <Loader2 size={16} className="animate-spin" />
                  Gerando pedido...
                </div>
              </div>
            )}

            {step === "done" && (
              <div className="space-y-4">
                <div className="text-lg font-semibold text-zinc-900">Orçamento aprovado com sucesso!</div>
                <div className="text-sm text-zinc-600">
                  Seu pedido foi gerado com sucesso. Você já pode baixar o PDF do pedido
                  {statusLink ? " e acompanhar o andamento dele." : "."}
                </div>
                {statusLink && (
                  <a
                    href={statusLink}
                    onClick={() => leituraDoOrcamento(token).acao("acompanhar")}
                    className="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-zinc-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-zinc-800 sm:w-auto"
                  >
                    <PackageSearch size={16} />
                    Acompanhar pedido
                  </a>
                )}
                {approvedOrder && (
                  <div className="rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-700">
                    {hideTotalInPublic
                      ? `Pedido #${approvedOrder.number}`
                      : `Pedido #${approvedOrder.number} • Total ${formatMoney(total)}`}
                  </div>
                )}
                <div className="flex flex-col sm:flex-row gap-2">
                  <button
                    type="button"
                    onClick={handleDownloadPdf}
                    className="inline-flex items-center justify-center gap-2 rounded-xl border border-zinc-200 bg-white px-5 py-2.5 text-sm font-semibold text-zinc-900 transition hover:bg-zinc-100"
                  >
                    <FileDown size={16} />
                    Baixar PDF
                  </button>
                  <button
                    type="button"
                    onClick={() => {
                      closeModal();
                      router.refresh();
                    }}
                    className="inline-flex items-center justify-center gap-2 rounded-xl bg-emerald-600 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-emerald-700"
                  >
                    Fechar
                  </button>
                </div>
              </div>
            )}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

type PublicQuoteTabsProps = {
  token: string;
  quoteId: string;
  quoteNumber: number;
  notificationTargetId: string;
  orderNumber?: number | null;
  currency: string;
  total: number;
  status?: string | null;
  logoUrl?: string | null;
  artGroups: PublicQuoteArtGroup[];
  requireSignature: boolean;
  artRegistrationEnabled: boolean;
  artApprovalRequired: boolean;
  hideTotalInPublic?: boolean;
  /* Link de acompanhamento do pedido; aparece na outra ponta da linha das abas
     assim que o orçamento vira pedido. */
  statusLink?: string | null;
  quoteContent: ReactNode;
};

export function PublicQuoteTabs({
  token,
  quoteId,
  quoteNumber,
  notificationTargetId,
  orderNumber,
  currency,
  total,
  status,
  logoUrl,
  artGroups,
  requireSignature,
  artRegistrationEnabled,
  artApprovalRequired,
  hideTotalInPublic = false,
  statusLink = null,
  quoteContent,
}: PublicQuoteTabsProps) {
  const [activeTab, setActiveTab] = useState<"quote" | "arts">("quote");
  const [artGroupsState, setArtGroupsState] = useState<PublicQuoteArtGroup[]>(artGroups);
  const allArts = useMemo(
    () => (artRegistrationEnabled ? artGroupsState.flatMap((group) => group.arts) : []),
    [artGroupsState, artRegistrationEnabled]
  );
  const pendingArts = useMemo(
    () => allArts.filter((art) => (art.approval_status || "pending") === "pending"),
    [allArts]
  );
  const approvedArts = useMemo(
    () => allArts.filter((art) => (art.approval_status || "pending") === "approved"),
    [allArts]
  );
  const rejectedArts = useMemo(
    () => allArts.filter((art) => (art.approval_status || "pending") === "rejected"),
    [allArts]
  );
  const pendingCount = pendingArts.length;
  const allArtsApproved = artApprovalRequired ? (allArts.length === 0 ? true : pendingCount === 0) : true;
  const hasOrder = Boolean(orderNumber);

  return (
    <div className="mt-6 space-y-4">
      <div className="print-hidden flex flex-wrap items-center justify-between gap-3">
      <div className="flex p-1 bg-[rgba(244,245,255,0.9)] rounded-xl w-full md:w-fit overflow-x-auto">
        <button
          onClick={() => setActiveTab("quote")}
          className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 whitespace-nowrap ${
            activeTab === "quote"
              ? "bg-white shadow-sm text-[var(--ks-color-text-primary)]"
              : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
          }`}
        >
          <FileText size={16} />
          {hideTotalInPublic ? "Lista de Preços" : "Orçamento"}
        </button>
        {artRegistrationEnabled && artGroupsState.length > 0 && (
          <button
            onClick={() => {
              setActiveTab("arts");
              leituraDoOrcamento(token).acao("artes");
            }}
            className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 whitespace-nowrap ${
              activeTab === "arts"
                ? "bg-white shadow-sm text-[var(--ks-color-text-primary)]"
                : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
            }`}
          >
            <ImageIcon size={16} />
            Artes
          </button>
        )}
      </div>
      {statusLink && (
        <a
          href={statusLink}
          onClick={() => leituraDoOrcamento(token).acao("acompanhar")}
          className="inline-flex w-full items-center justify-center gap-2 rounded-xl bg-zinc-900 px-4 py-2.5 text-sm font-semibold text-white shadow-sm transition hover:bg-zinc-800 md:w-auto"
        >
          <PackageSearch size={16} />
          Acompanhar pedido
        </a>
      )}
      </div>

      <div className={activeTab === "quote" ? "block" : "hidden print:block"}>
        <PublicQuoteActions
          token={token}
          quoteId={quoteId}
          quoteNumber={quoteNumber}
          notificationTargetId={notificationTargetId}
          orderNumber={orderNumber}
          currency={currency}
          total={total}
          status={status}
          logoUrl={logoUrl}
          pendingArtsCount={pendingCount}
          hasArts={allArts.length > 0}
          allArtsApproved={allArtsApproved}
          requireSignature={requireSignature}
          artApprovalRequired={artApprovalRequired}
          hideTotalInPublic={hideTotalInPublic}
          statusLink={statusLink}
        />
        {quoteContent}
      </div>

      <div className={activeTab === "arts" ? "block print-hidden" : "hidden print-hidden"}>
        <PublicQuoteArtsPanel
          token={token}
          quoteId={quoteId}
          quoteNumber={quoteNumber}
          notificationTargetId={notificationTargetId}
          hasOrder={hasOrder}
          artGroups={artGroupsState}
          pendingArts={pendingArts}
          approvedArts={approvedArts}
          rejectedArts={rejectedArts}
          setArtGroupsState={setArtGroupsState}
        />
      </div>
    </div>
  );
}

type PublicQuoteArtsPanelProps = {
  token: string;
  quoteId: string;
  quoteNumber: number;
  notificationTargetId: string;
  hasOrder: boolean;
  artGroups: PublicQuoteArtGroup[];
  pendingArts: PublicQuoteArt[];
  approvedArts: PublicQuoteArt[];
  rejectedArts: PublicQuoteArt[];
  setArtGroupsState: React.Dispatch<React.SetStateAction<PublicQuoteArtGroup[]>>;
};

function PublicQuoteArtsPanel({
  token,
  quoteId,
  quoteNumber,
  notificationTargetId,
  hasOrder,
  artGroups,
  pendingArts,
  approvedArts,
  rejectedArts,
  setArtGroupsState,
}: PublicQuoteArtsPanelProps) {
  const [activeTab, setActiveTab] = useState<"pending" | "approved" | "rejected">("pending");
  const [reviewingArtId, setReviewingArtId] = useState<string | null>(null);
  const [reviewError, setReviewError] = useState<{ artId: string; message: string } | null>(null);
  const [rejectModalOpen, setRejectModalOpen] = useState(false);
  const [rejectArtId, setRejectArtId] = useState<string | null>(null);
  const [rejectNote, setRejectNote] = useState("");
  const [rejectError, setRejectError] = useState("");
  const [artMessageDrafts, setArtMessageDrafts] = useState<Record<string, string>>({});
  const [artMessageSending, setArtMessageSending] = useState<Record<string, boolean>>({});
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
  const [historyOpen, setHistoryOpen] = useState(false);
  const chatChannelRef = useRef<RealtimeChannel | null>(null);
  const notificationChannelRef = useRef<RealtimeChannel | null>(null);
  const readIdsRef = useRef<Set<string>>(new Set());

  const filteredArts =
    activeTab === "pending" ? pendingArts : activeTab === "approved" ? approvedArts : rejectedArts;
  const filteredArtsSet = new Set(filteredArts.map((art) => art.id));
  const filteredGroups = artGroups
    .map((group) => ({
      ...group,
      arts: group.arts.filter((art) => filteredArtsSet.has(art.id)),
    }))
    .filter((group) => group.arts.length > 0);
  const formatMessageDate = (value?: string | null) => {
    if (!value) return "";
    const parsed = new Date(value);
    if (Number.isNaN(parsed.getTime())) return "";
    return parsed.toLocaleString("pt-BR", { dateStyle: "short", timeStyle: "short" });
  };
  const resolveStatusLabel = (value?: string | null) => {
    if (value === "approved") return "Aprovada";
    if (value === "rejected") return "Reprovada";
    if (value === "updated") return "Atualização";
    return "";
  };
  const rejectArt = rejectArtId
    ? artGroups.flatMap((group) => group.arts).find((art) => art.id === rejectArtId) || null
    : null;

  const notifyAdmin = async (payload: {
    id: string;
    quote_id: string;
    art_id: string;
    message: string;
    created_at: string;
    kind: "chat" | "art_approved" | "art_rejected";
    quote_number: number;
    target_user_id?: string;
  }) => {
    if (!notificationChannelRef.current) return;
    await notificationChannelRef.current.send({
      type: "broadcast",
      event: "client_message",
      payload,
    });
  };

  async function handleReviewArt(artId: string, statusValue: "approved" | "rejected", note: string) {
    if (reviewingArtId) return false;
    const current = artGroups.flatMap((group) => group.arts).find((art) => art.id === artId);
    const currentStatus = current?.approval_status || "pending";
    if (currentStatus !== "pending") {
      setReviewError({ artId, message: "Esta arte já foi revisada." });
      return false;
    }
    setReviewingArtId(artId);
    setReviewError(null);
    try {
      const supabase = getSupabaseClient();
      const { data, error } = await supabase.rpc("review_public_quote_art", {
        p_token: token,
        p_art_id: artId,
        p_status: statusValue,
        p_notes: note || null,
      });
      if (error) throw error;
      const now = typeof data?.message_created_at === "string" ? data.message_created_at : new Date().toISOString();
      const messageId = typeof data?.message_id === "string" ? data.message_id : `local-${artId}-${now}`;
      const messageText =
        note || (statusValue === "approved" ? "Arte aprovada." : "Arte reprovada.");
      setArtGroupsState((prev) =>
        prev.map((group) => ({
          ...group,
          arts: group.arts.map((art) =>
            art.id === artId
              ? {
                  ...art,
                  approval_status: statusValue,
                  approval_notes: note || null,
                  reviewed_at: now,
                  approved_at: statusValue === "approved" ? now : null,
                  messages: [
                    ...(art.messages || []),
                    {
                      id: messageId,
                      sender: "client",
                      message: messageText,
                      status: statusValue,
                      created_at: now,
                      delivered_at: null,
                      read_at: null,
                    },
                  ],
                }
              : art
          ),
        }))
      );
      if (current?.quote_item_id && chatChannelRef.current) {
        await chatChannelRef.current.send({
          type: "broadcast",
          event: "message",
          payload: {
            id: messageId,
            quote_id: quoteId,
            quote_item_id: current.quote_item_id,
            art_id: artId,
            sender: "client",
            message: messageText,
            status: statusValue,
            created_at: now,
            delivered_at: null,
            read_at: null,
          },
        });
      }
      await notifyAdmin({
        id: messageId,
        quote_id: quoteId,
        art_id: artId,
        message: messageText,
        created_at: now,
        kind: statusValue === "approved" ? "art_approved" : "art_rejected",
        quote_number: quoteNumber,
        target_user_id: notificationTargetId,
      });
      setArtMessageDrafts((prev) => ({ ...prev, [artId]: "" }));
      return true;
    } catch (err) {
      const message =
        typeof err === "object" && err && "message" in err && typeof err.message === "string"
          ? err.message
          : "Não foi possível registrar a revisão da arte.";
      setReviewError({ artId, message });
      return false;
    } finally {
      setReviewingArtId(null);
    }
  }

  async function handleSendArtMessage(artId: string) {
    if (artMessageSending[artId]) return;
    const current = artGroups.flatMap((group) => group.arts).find((art) => art.id === artId);
    if ((current?.approval_status || "pending") === "approved") return;
    const text = (artMessageDrafts[artId] ?? "").trim();
    if (!text) return;
    setArtMessageSending((prev) => ({ ...prev, [artId]: true }));
    setReviewError(null);
    try {
      const supabase = getSupabaseClient();
      const { data, error } = await supabase.rpc("send_public_quote_art_message", {
        p_token: token,
        p_art_id: artId,
        p_message: text,
        p_status: null,
      });
      if (error) throw error;
      const now = typeof data?.message_created_at === "string" ? data.message_created_at : new Date().toISOString();
      const messageId = typeof data?.message_id === "string" ? data.message_id : `local-message-${artId}-${now}`;
      const current = artGroups.flatMap((group) => group.arts).find((art) => art.id === artId);
      setArtGroupsState((prev) =>
        prev.map((group) => ({
          ...group,
          arts: group.arts.map((art) =>
            art.id === artId
              ? {
                  ...art,
                  messages: [
                    ...(art.messages || []),
                    {
                      id: messageId,
                      sender: "client",
                      message: text,
                      status: null,
                      created_at: now,
                      delivered_at: null,
                      read_at: null,
                    },
                  ],
                }
              : art
          ),
        }))
      );
      if (current?.quote_item_id && chatChannelRef.current) {
        await chatChannelRef.current.send({
          type: "broadcast",
          event: "message",
          payload: {
            id: messageId,
            quote_id: quoteId,
            quote_item_id: current.quote_item_id,
            art_id: artId,
            sender: "client",
            message: text,
            status: null,
            created_at: now,
            delivered_at: null,
            read_at: null,
          },
        });
      }
      await notifyAdmin({
        id: messageId,
        quote_id: quoteId,
        art_id: artId,
        message: text,
        created_at: now,
        kind: "chat",
        quote_number: quoteNumber,
        target_user_id: notificationTargetId,
      });
      setArtMessageDrafts((prev) => ({ ...prev, [artId]: "" }));
    } catch (err) {
      const message =
        typeof err === "object" && err && "message" in err && typeof err.message === "string"
          ? err.message
          : "Não foi possível enviar a mensagem.";
      setReviewError({ artId, message });
    } finally {
      setArtMessageSending((prev) => ({ ...prev, [artId]: false }));
    }
  }

  useEffect(() => {
    const supabase = getSupabaseClient();
    const channel = supabase.channel("admin-notifications");
    channel.subscribe();
    notificationChannelRef.current = channel;
    return () => {
      supabase.removeChannel(channel);
      notificationChannelRef.current = null;
    };
  }, []);

  useEffect(() => {
    if (!quoteId) return;
    const supabase = getSupabaseClient();
    const channel = supabase.channel(`quote-chat-${quoteId}`);
    channel.on("broadcast", { event: "message" }, ({ payload }) => {
      const incoming = payload as (PublicQuoteArtMessage & { art_id?: string });
      if (!incoming?.id || !incoming?.art_id) return;
      setArtGroupsState((prev) =>
        prev.map((group) => ({
          ...group,
          arts: group.arts.map((art) => {
            if (art.id !== incoming.art_id) return art;
            const messages = art.messages || [];
            if (messages.some((m) => m.id === incoming.id)) return art;
            return {
              ...art,
              messages: [...messages, incoming],
            };
          }),
        }))
      );
    });
    channel.on("broadcast", { event: "art_updated" }, ({ payload }) => {
      const incoming = payload as Partial<PublicQuoteArt> & { art_id?: string };
      if (!incoming?.art_id) return;
      setArtGroupsState((prev) =>
        prev.map((group) => ({
          ...group,
          arts: group.arts.map((art) =>
            art.id === incoming.art_id
              ? {
                  ...art,
                  title: incoming.title ?? art.title,
                  notes: incoming.notes ?? art.notes,
                  image_urls: Array.isArray(incoming.image_urls) ? incoming.image_urls : art.image_urls,
                  approval_status: incoming.approval_status ?? art.approval_status,
                  approval_notes: incoming.approval_notes ?? art.approval_notes,
                  approved_at: incoming.approved_at ?? art.approved_at,
                  reviewed_at: incoming.reviewed_at ?? art.reviewed_at,
                }
              : art
          ),
        }))
      );
    });
    channel.on("broadcast", { event: "receipt" }, ({ payload }) => {
      const receipt = payload as { id?: string; delivered_at?: string | null; read_at?: string | null };
      if (!receipt?.id) return;
      setArtGroupsState((prev) =>
        prev.map((group) => ({
          ...group,
          arts: group.arts.map((art) => ({
            ...art,
            messages: (art.messages || []).map((message) =>
              message.id === receipt.id
                ? {
                    ...message,
                    delivered_at: receipt.delivered_at ?? message.delivered_at,
                    read_at: receipt.read_at ?? message.read_at,
                  }
                : message
            ),
          })),
        }))
      );
    });
    channel.subscribe();
    chatChannelRef.current = channel;
    return () => {
      supabase.removeChannel(channel);
      chatChannelRef.current = null;
    };
  }, [quoteId, setArtGroupsState]);

  useEffect(() => {
    let active = true;
    async function markReceipts() {
      if (!artGroups.length) return;
      const supabase = getSupabaseClient();
      const pendingRead: PublicQuoteArtMessage[] = [];
      artGroups.forEach((group) => {
        group.arts.forEach((art) => {
          (art.messages || []).forEach((message) => {
            if (message.sender !== "company") return;
            if (message.read_at) return;
            if (readIdsRef.current.has(message.id)) return;
            pendingRead.push(message);
          });
        });
      });
      for (const message of pendingRead) {
        readIdsRef.current.add(message.id);
        const { error } = await supabase.rpc("mark_public_quote_art_message_read", {
          p_token: token,
          p_message_id: message.id,
        });
        if (!active || error) continue;
        const now = new Date().toISOString();
        setArtGroupsState((prev) =>
          prev.map((group) => ({
            ...group,
            arts: group.arts.map((art) => ({
              ...art,
              messages: (art.messages || []).map((msg) =>
                msg.id === message.id
                  ? {
                      ...msg,
                      delivered_at: msg.delivered_at ?? now,
                      read_at: msg.read_at ?? now,
                    }
                  : msg
              ),
            })),
          }))
        );
        if (chatChannelRef.current) {
          await chatChannelRef.current.send({
            type: "broadcast",
            event: "receipt",
            payload: { id: message.id, delivered_at: now, read_at: now },
          });
        }
      }
    }
    markReceipts();
    return () => {
      active = false;
    };
  }, [artGroups, token, setArtGroupsState]);

  const historyGroups = artGroups.filter((group) => group.arts.length > 0);

  return (
    <div className="rounded-2xl border border-zinc-200 bg-white p-5 shadow-sm">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <div className="text-sm font-semibold text-zinc-900">Aprovação das artes</div>
          <div className="text-xs text-zinc-600">Revise as imagens e aprove ou reprove.</div>
        </div>
        <div className="flex items-center gap-2 text-xs text-zinc-600">
          <span className="px-3 py-1 rounded-full bg-amber-50 text-amber-700 border border-amber-200 font-semibold">
            {pendingArts.length} pendente(s)
          </span>
          {hasOrder && (
            <button
              type="button"
              onClick={() => setHistoryOpen(true)}
              className="inline-flex items-center justify-center rounded-full border border-zinc-200 px-3 py-1 text-[11px] font-semibold text-zinc-700 transition hover:bg-zinc-50"
            >
              Ver histórico
            </button>
          )}
        </div>
      </div>

      {!hasOrder && (
        <div className="mt-4 flex p-1 bg-[rgba(244,245,255,0.9)] rounded-xl w-full md:w-fit overflow-x-auto">
          <button
            onClick={() => setActiveTab("pending")}
            className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 whitespace-nowrap ${
              activeTab === "pending"
                ? "bg-white shadow-sm text-[var(--ks-color-text-primary)]"
                : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
            }`}
          >
            <Clock size={16} />
            Pendentes
          </button>
          <button
            onClick={() => setActiveTab("approved")}
            className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 whitespace-nowrap ${
              activeTab === "approved"
                ? "bg-white shadow-sm text-[var(--ks-color-text-primary)]"
                : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
            }`}
          >
            <CheckCircle2 size={16} />
            Aprovadas
          </button>
          <button
            onClick={() => setActiveTab("rejected")}
            className={`px-4 py-2 rounded-lg text-sm font-medium transition-all flex items-center gap-2 whitespace-nowrap ${
              activeTab === "rejected"
                ? "bg-white shadow-sm text-[var(--ks-color-text-primary)]"
                : "text-[var(--ks-color-text-muted)] hover:text-[var(--ks-color-text-primary)]"
            }`}
          >
            <XCircle size={16} />
            Reprovadas
          </button>
        </div>
      )}

      {reviewError && <div className="mt-3 text-sm text-red-600">{reviewError.message}</div>}

      {hasOrder ? (
        <div className="mt-4 grid gap-4 sm:grid-cols-2 md:grid-cols-3">
          {artGroups.flatMap((group) =>
            group.arts.flatMap((art) =>
              (art.image_urls || []).map((url) => (
                <div key={`${art.id}-${url}`} className="space-y-2">
                  <button
                    type="button"
                    onClick={() => setPreviewUrl(url)}
                    className="group relative w-full aspect-[4/3] min-h-[160px] overflow-hidden rounded-xl border border-zinc-200 bg-white"
                  >
                    <Image
                      src={url}
                      alt="Arte aprovada"
                      fill
                      sizes="(min-width: 768px) 33vw, 100vw"
                      className="object-contain transition duration-300 group-hover:scale-[1.02]"
                      unoptimized
                    />
                    <span className="absolute left-2 top-2 rounded-full bg-emerald-600 px-2 py-1 text-[10px] font-semibold text-white">
                      Aprovada
                    </span>
                  </button>
                  <div className="text-xs font-semibold text-zinc-800">
                    {group.itemTitle || "Item sem título"}
                  </div>
                </div>
              ))
            )
          )}
        </div>
      ) : filteredArts.length === 0 ? (
        <div className="mt-6 text-sm text-zinc-600">Nenhuma arte nesta aba.</div>
      ) : (
        <div className="mt-4 space-y-4">
          {filteredGroups.map((group) => (
            <div key={group.itemId} className="rounded-xl border border-zinc-200 p-4">
              <div className="flex flex-col gap-1">
                <div className="text-sm font-semibold text-zinc-900">
                  Item {group.itemIndex} — {group.itemTitle || "Item sem título"}
                </div>
                {group.itemDescription && <div className="text-xs text-zinc-600">{group.itemDescription}</div>}
              </div>
              <div className="mt-3 space-y-4">
                {group.arts.map((art) => {
                  const status = art.approval_status || "pending";
                  const statusLabel =
                    status === "approved" ? "Aprovada" : status === "rejected" ? "Reprovada" : "Pendente";
                  const statusColor =
                    status === "approved"
                      ? "bg-emerald-50 text-emerald-700 border-emerald-200"
                      : status === "rejected"
                        ? "bg-rose-50 text-rose-700 border-rose-200"
                        : "bg-amber-50 text-amber-700 border-amber-200";
                  const isFinalized = status !== "pending";
                  const isChatBlocked = status === "approved";
                  const messages = Array.isArray(art.messages) ? art.messages : [];
                  const sortedMessages = [...messages].sort((a, b) =>
                    new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime()
                  );
                  const chatDraft = artMessageDrafts[art.id] ?? "";
                  const isSending = artMessageSending[art.id] || false;
                  return (
                    <div key={art.id} className="rounded-xl border border-zinc-200 p-4">
                      <div className="flex flex-wrap items-center justify-between gap-2">
                        <div className="min-w-0">
                          <div className="text-sm font-semibold text-zinc-900">{art.title || "Arte"}</div>
                          {art.notes && <div className="text-xs text-zinc-600 mt-1">{art.notes}</div>}
                        </div>
                        <div className={`text-xs font-semibold px-2 py-1 rounded-full border ${statusColor}`}>
                          {statusLabel}
                        </div>
                      </div>
                      {art.image_urls?.length > 0 && (
                        <div className="mt-3 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-3">
                          {art.image_urls.map((url) => (
                            <button
                              key={url}
                              type="button"
                              onClick={() => setPreviewUrl(url)}
                              className="group relative w-full aspect-[4/3] min-h-[160px] overflow-hidden rounded-xl border border-zinc-200 bg-white"
                            >
                              <Image
                                src={url}
                                alt="Arte"
                                fill
                                sizes="(min-width: 768px) 33vw, 100vw"
                                className="object-contain transition duration-300 group-hover:scale-[1.02]"
                                unoptimized
                              />
                            </button>
                          ))}
                        </div>
                      )}
                      {!isFinalized && (
                        <div className="mt-3 space-y-2">
                          <div className="flex flex-col sm:flex-row gap-2">
                            <button
                              type="button"
                              onClick={() => handleReviewArt(art.id, "approved", "")}
                              disabled={reviewingArtId === art.id}
                              className="inline-flex items-center justify-center gap-2 rounded-xl bg-emerald-600 px-4 py-2 text-xs font-semibold text-white transition hover:bg-emerald-700 disabled:cursor-not-allowed disabled:bg-emerald-300"
                            >
                              {reviewingArtId === art.id ? <Loader2 size={14} className="animate-spin" /> : null}
                              Aprovar arte
                            </button>
                            <button
                              type="button"
                              onClick={() => {
                                setRejectArtId(art.id);
                                setRejectNote("");
                                setRejectError("");
                                setRejectModalOpen(true);
                              }}
                              disabled={reviewingArtId === art.id}
                              className="inline-flex items-center justify-center gap-2 rounded-xl border border-rose-200 px-4 py-2 text-xs font-semibold text-rose-700 transition hover:bg-rose-50 disabled:cursor-not-allowed disabled:opacity-60"
                            >
                              {reviewingArtId === art.id ? <Loader2 size={14} className="animate-spin" /> : null}
                              Reprovar arte
                            </button>
                          </div>
                          {reviewError?.artId === art.id ? (
                            <div className="text-xs text-rose-600">{reviewError.message}</div>
                          ) : null}
                        </div>
                      )}
                      <div className="mt-4 rounded-xl border border-zinc-200 bg-zinc-50 p-3">
                        <div className="text-xs font-semibold text-zinc-700">Chat com a equipe</div>
                        {sortedMessages.length > 0 ? (
                          <div className="mt-2 space-y-2">
                            {sortedMessages.map((message) => {
                              const senderLabel = message.sender === "client" ? "Cliente" : "Empresa";
                              const statusLabel = resolveStatusLabel(message.status);
                              const statusBadgeClass =
                                message.status === "approved"
                                  ? "bg-emerald-100 text-emerald-700"
                                  : message.status === "rejected"
                                    ? "bg-rose-100 text-rose-700"
                                    : message.status === "updated"
                                      ? "bg-blue-100 text-blue-700"
                                      : "bg-zinc-100 text-zinc-500";
                              const dateLabel = formatMessageDate(message.created_at);
                              const alignClass = message.sender === "client" ? "justify-start" : "justify-end";
                              const isOutgoing = message.sender === "client";
                              const hasRead = Boolean(message.read_at);
                              const hasDelivered = Boolean(message.delivered_at);
                              const statusClass = hasRead
                                ? "text-emerald-500"
                                : hasDelivered
                                  ? "text-zinc-400"
                                  : "text-zinc-300";
                              const bubbleClass =
                                message.sender === "client"
                                  ? "bg-white text-zinc-900 border border-zinc-200"
                                  : "bg-[#4b2ae6] text-white border border-[#4b2ae6]";
                              return (
                                <div key={message.id} className={`flex ${alignClass}`}>
                                  <div className={`max-w-[85%] rounded-xl px-3 py-2 text-xs ${bubbleClass}`}>
                                    <div className="flex flex-wrap items-center gap-2 text-[10px] opacity-80">
                                      <span className="font-semibold">{senderLabel}</span>
                                      {statusLabel ? (
                                        <span className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${statusBadgeClass}`}>
                                          {statusLabel}
                                        </span>
                                      ) : null}
                                      {dateLabel && <span>{dateLabel}</span>}
                                      {isOutgoing && (
                                        <span className={`inline-flex items-center ${statusClass}`}>
                                          <Check size={12} />
                                          {(hasDelivered || hasRead) && <Check size={12} className="-ml-2" />}
                                        </span>
                                      )}
                                    </div>
                                    <div className="mt-1 text-sm leading-relaxed">{message.message}</div>
                                  </div>
                                </div>
                              );
                            })}
                          </div>
                        ) : (
                          <div className="mt-2 text-xs text-zinc-500">Nenhuma mensagem ainda.</div>
                        )}
                        <div className="mt-3 space-y-2">
                          <textarea
                            value={chatDraft}
                            onChange={(event) =>
                              setArtMessageDrafts((prev) => ({ ...prev, [art.id]: event.target.value }))
                            }
                            rows={3}
                            placeholder={
                              isChatBlocked ? "Esta arte já foi aprovada." : "Escreva sua mensagem para a equipe"
                            }
                            className="w-full rounded-xl border border-zinc-200 px-3 py-2 text-sm text-zinc-700 focus:border-[#4b2ae6] focus:outline-none"
                            disabled={isChatBlocked}
                          />
                          <div className="flex flex-wrap gap-2">
                            <button
                              type="button"
                              onClick={() => handleSendArtMessage(art.id)}
                              disabled={isSending || isChatBlocked || !chatDraft.trim()}
                              className="inline-flex items-center justify-center gap-2 rounded-xl bg-[#4b2ae6] px-4 py-2 text-xs font-semibold text-white transition hover:bg-[#3f22c2] disabled:cursor-not-allowed disabled:bg-zinc-300"
                            >
                              {isSending ? <Loader2 size={14} className="animate-spin" /> : null}
                              Enviar mensagem
                            </button>
                            {!isFinalized && !isChatBlocked && (
                              <div className="text-[10px] text-zinc-500 flex items-center">
                                Use o chat para conversar com a equipe.
                              </div>
                            )}
                            {isChatBlocked && (
                              <div className="text-[10px] text-zinc-500 flex items-center">
                                Chat bloqueado após aprovação.
                              </div>
                            )}
                          </div>
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      )}

      {historyOpen ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="absolute inset-0 bg-black/60 backdrop-blur-[2px]" onClick={() => setHistoryOpen(false)} />
          <div className="relative w-full max-w-3xl rounded-2xl bg-white p-5 shadow-2xl max-h-[80vh] overflow-auto">
            <div className="flex items-center justify-between gap-3">
              <div className="text-sm font-semibold text-zinc-900">Histórico de conversas</div>
              <button
                type="button"
                onClick={() => setHistoryOpen(false)}
                className="inline-flex items-center justify-center rounded-full border border-zinc-200 px-3 py-1 text-[11px] font-semibold text-zinc-700 transition hover:bg-zinc-50"
              >
                Fechar
              </button>
            </div>
            <div className="mt-4 space-y-4">
              {historyGroups.length === 0 ? (
                <div className="text-xs text-zinc-500">Nenhuma conversa registrada.</div>
              ) : (
                historyGroups.map((group) => (
                  <div key={group.itemId} className="rounded-xl border border-zinc-200 p-4">
                    <div className="text-sm font-semibold text-zinc-900">
                      Item {group.itemIndex} — {group.itemTitle || "Item sem título"}
                    </div>
                    {group.arts.map((art) => {
                      const messages = Array.isArray(art.messages) ? art.messages : [];
                      const sortedMessages = [...messages].sort((a, b) =>
                        new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime()
                      );
                      return (
                        <div key={art.id} className="mt-3 rounded-xl border border-zinc-200 bg-zinc-50 p-3">
                          <div className="text-xs font-semibold text-zinc-700">{art.title || "Arte"}</div>
                          {sortedMessages.length > 0 ? (
                            <div className="mt-2 space-y-2">
                              {sortedMessages.map((message) => {
                                const senderLabel = message.sender === "client" ? "Cliente" : "Empresa";
                                const statusLabel = resolveStatusLabel(message.status);
                                const statusBadgeClass =
                                  message.status === "approved"
                                    ? "bg-emerald-100 text-emerald-700"
                                    : message.status === "rejected"
                                      ? "bg-rose-100 text-rose-700"
                                      : message.status === "updated"
                                        ? "bg-blue-100 text-blue-700"
                                        : "bg-zinc-100 text-zinc-500";
                                const dateLabel = formatMessageDate(message.created_at);
                                return (
                                  <div key={message.id} className="rounded-xl border border-zinc-200 bg-white px-3 py-2 text-xs">
                                    <div className="flex flex-wrap items-center gap-2 text-[10px] text-zinc-500">
                                      <span className="font-semibold text-zinc-700">{senderLabel}</span>
                                      {statusLabel ? (
                                        <span className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${statusBadgeClass}`}>
                                          {statusLabel}
                                        </span>
                                      ) : null}
                                      {dateLabel && <span>{dateLabel}</span>}
                                    </div>
                                    <div className="mt-1 text-sm text-zinc-800">{message.message}</div>
                                  </div>
                                );
                              })}
                            </div>
                          ) : (
                            <div className="mt-2 text-xs text-zinc-500">Nenhuma mensagem.</div>
                          )}
                        </div>
                      );
                    })}
                  </div>
                ))
              )}
            </div>
          </div>
        </div>
      ) : null}

      {rejectModalOpen ? (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div
            className="absolute inset-0 bg-black/60 backdrop-blur-[2px]"
            onClick={() => {
              setRejectModalOpen(false);
              setRejectArtId(null);
              setRejectNote("");
              setRejectError("");
            }}
          />
          <div className="relative w-full max-w-lg rounded-2xl bg-white p-5 shadow-2xl">
            <div className="text-sm font-semibold text-zinc-900">Reprovar arte</div>
            <div className="mt-1 text-xs text-zinc-600">
              {rejectArt ? `${rejectArt.title || "Arte sem título"} — informe as alterações desejadas.` : "Informe as alterações desejadas."}
            </div>
            <div className="mt-4 space-y-2">
              <textarea
                value={rejectNote}
                onChange={(event) => setRejectNote(event.target.value)}
                rows={4}
                placeholder="Descreva as alterações para reprovar esta arte"
                className="w-full rounded-xl border border-zinc-200 px-3 py-2 text-sm text-zinc-700 focus:border-[#4b2ae6] focus:outline-none"
              />
              {rejectError ? <div className="text-xs text-rose-600">{rejectError}</div> : null}
            </div>
            <div className="mt-4 flex flex-wrap justify-end gap-2">
              <button
                type="button"
                onClick={() => {
                  setRejectModalOpen(false);
                  setRejectArtId(null);
                  setRejectNote("");
                  setRejectError("");
                }}
                className="inline-flex items-center justify-center rounded-xl border border-zinc-200 px-4 py-2 text-xs font-semibold text-zinc-700 transition hover:bg-zinc-50"
              >
                Cancelar
              </button>
              <button
                type="button"
                disabled={!rejectArtId || reviewingArtId === rejectArtId}
                onClick={async () => {
                  const trimmed = rejectNote.trim();
                  if (!trimmed) {
                    setRejectError("Descreva as alterações desejadas antes de reprovar.");
                    return;
                  }
                  if (!rejectArtId) return;
                  const ok = await handleReviewArt(rejectArtId, "rejected", trimmed);
                  if (!ok) return;
                  setRejectModalOpen(false);
                  setRejectArtId(null);
                  setRejectNote("");
                  setRejectError("");
                }}
                className="inline-flex items-center justify-center gap-2 rounded-xl bg-rose-600 px-4 py-2 text-xs font-semibold text-white transition hover:bg-rose-700 disabled:cursor-not-allowed disabled:bg-rose-300"
              >
                {reviewingArtId === rejectArtId ? <Loader2 size={14} className="animate-spin" /> : null}
                Reprovar e enviar
              </button>
            </div>
          </div>
        </div>
      ) : null}

      {previewUrl && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="absolute inset-0 bg-black/60 backdrop-blur-[2px]" onClick={() => setPreviewUrl(null)} />
          <div className="relative w-full max-w-5xl rounded-2xl bg-white p-4 shadow-2xl">
            <button
              type="button"
              onClick={() => setPreviewUrl(null)}
              className="absolute right-3 top-3 rounded-full p-2 text-zinc-600 transition hover:bg-zinc-100"
              aria-label="Fechar"
            >
              <X size={16} />
            </button>
            <Image
              src={previewUrl}
              alt="Arte ampliada"
              width={1200}
              height={800}
              sizes="90vw"
              className="max-h-[80vh] w-full object-contain rounded-xl"
              unoptimized
            />
          </div>
        </div>
      )}
    </div>
  );
}
