import { cache } from "react";
import type { Metadata } from "next";
import Image from "next/image";
import Link from "next/link";
import { notFound } from "next/navigation";
import { Download } from "lucide-react";
import { createAdminClient } from "@/lib/supabase-server";
import { verifySupplierPurchaseOrderPublicToken } from "@/lib/supplier-purchase-order-public";
import { PrintTrigger } from "./print-trigger";

export const dynamic = "force-dynamic";
export const revalidate = 0;

type PublicPurchasePageProps = {
  params: Promise<{ token: string }>;
  searchParams: Promise<{ print?: string }>;
};

type PurchaseStatus = "draft" | "ordered" | "partial" | "received" | "canceled";

type PurchaseItemRow = {
  id: string;
  material_name: string | null;
  unit: string | null;
  quantity: number | null;
  unit_price: number | null;
  total_price: number | null;
  notes: string | null;
};

type PurchaseRow = {
  id: string;
  company_id: string;
  supplier_id: string;
  created_by?: string | null;
  order_number: number | null;
  description: string | null;
  total_amount: number | null;
  shipping_amount?: number | null;
  discount_amount?: number | null;
  tax_amount?: number | null;
  status: string | null;
  ordered_at: string | null;
  expected_at: string | null;
  notes: string | null;
  created_at: string | null;
};

type SupplierRow = {
  id: string;
  name: string | null;
  cnpj: string | null;
  email: string | null;
  phone: string | null;
};

type ProfileRow = {
  id?: string;
  full_name?: string | null;
  catalog_name?: string | null;
  store_name?: string | null;
  logo_url?: string | null;
  catalog_logo_url?: string | null;
  cnpj?: string | null;
  company_phone?: string | null;
  phone?: string | null;
  company_email?: string | null;
  address?: string | null;
  address_zip?: string | null;
  address_street?: string | null;
  address_number?: string | null;
  address_complement?: string | null;
  address_neighborhood?: string | null;
  address_city?: string | null;
  address_state?: string | null;
};

type CompanyUserRow = {
  user_id?: string | null;
  role?: string | null;
};

type PublicPurchasePayload = {
  purchase: PurchaseRow;
  supplier: SupplierRow | null;
  items: PurchaseItemRow[];
  profile: ProfileRow | null;
  payable: {
    payment_method: string | null;
    payment_date: string | null;
    due_date: string | null;
    status: string | null;
  } | null;
};

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

function formatDate(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 [year, month, day] = parts;
    return `${day}/${month}/${year}`;
  }
  const date = new Date(value);
  if (!Number.isFinite(date.getTime())) return "-";
  return date.toLocaleDateString("pt-BR");
}

function formatDocument(value: string | null | undefined) {
  const digits = String(value || "").replace(/\D/g, "");
  if (digits.length === 14) {
    return digits.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
  }
  if (digits.length === 11) {
    return digits.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
  }
  return String(value || "").trim() || "-";
}

function statusLabel(status: string | null | undefined) {
  const normalized = String(status || "").toLowerCase() as PurchaseStatus;
  const labels: Record<PurchaseStatus, string> = {
    draft: "Rascunho",
    ordered: "Pedido emitido",
    partial: "Recebimento parcial",
    received: "Recebido",
    canceled: "Cancelado",
  };
  return labels[normalized] || "Rascunho";
}

function formatQuantity(value: number | null | undefined) {
  const safe = Number(value || 0);
  return new Intl.NumberFormat("pt-BR", {
    minimumFractionDigits: Number.isInteger(safe) ? 0 : 2,
    maximumFractionDigits: 2,
  }).format(safe);
}

function hasValue(value: string | null | undefined) {
  return String(value || "").trim().length > 0;
}

function resolveProfileName(profile: ProfileRow | null | undefined) {
  return (
    profile?.store_name ||
    profile?.catalog_name ||
    profile?.full_name ||
    "Comprador"
  );
}

function buildAddress(profile: ProfileRow | null | undefined) {
  if (!profile) return "";
  if (hasValue(profile.address)) return String(profile.address).trim();

  const streetLine = [
    profile.address_street,
    profile.address_number,
    profile.address_complement,
  ]
    .filter((value) => hasValue(value))
    .join(", ");
  const locationLine = [
    profile.address_neighborhood,
    profile.address_city,
    profile.address_state,
    profile.address_zip,
  ]
    .filter((value) => hasValue(value))
    .join(" - ");

  return [streetLine, locationLine].filter(Boolean).join(" | ");
}

function paymentMethodLabel(value: string | null | undefined) {
  const normalized = String(value || "").trim().toLowerCase();
  const labels: Record<string, string> = {
    pix: "Pix",
    cash: "Dinheiro",
    credit_card: "Cartao de credito",
    debit_card: "Cartao de debito",
    transfer: "Transferencia",
    boleto: "Boleto",
  };
  return labels[normalized] || "Nao informada";
}

function profileBusinessScore(profile: ProfileRow | null | undefined) {
  if (!profile) return 0;
  let score = 0;
  if (hasValue(profile.store_name)) score += 5;
  if (hasValue(profile.catalog_name)) score += 4;
  if (hasValue(profile.full_name)) score += 2;
  if (hasValue(profile.cnpj)) score += 4;
  if (hasValue(profile.company_phone) || hasValue(profile.phone)) score += 2;
  if (hasValue(profile.company_email)) score += 2;
  if (hasValue(buildAddress(profile))) score += 3;
  return score;
}

function companyRoleWeight(role: string | null | undefined) {
  switch (String(role || "").toLowerCase()) {
    case "owner":
      return 5;
    case "admin":
      return 4;
    case "manager":
      return 3;
    case "financial":
      return 2;
    default:
      return 1;
  }
}

function pickBestCompanyProfile(
  rows: ProfileRow[],
  context: {
    createdBy?: string | null;
    ownerId?: string | null;
    companyUsers: CompanyUserRow[];
  }
) {
  const companyUserIds = new Set(context.companyUsers.map((item) => item.user_id).filter(Boolean));
  const roleByUserId = new Map(
    context.companyUsers
      .filter((item) => item.user_id)
      .map((item) => [String(item.user_id), companyRoleWeight(item.role)])
  );

  const ranked = [...rows].sort((left, right) => {
    const leftId = String(left.id || "");
    const rightId = String(right.id || "");
    const leftPriority =
      profileBusinessScore(left) * 1000 +
      (leftId && leftId === context.ownerId ? 100 : 0) +
      (leftId && leftId === context.createdBy ? 80 : 0) +
      (leftId && companyUserIds.has(leftId) ? 40 : 0) +
      (roleByUserId.get(leftId) || 0) * 5;
      
    const rightPriority =
      profileBusinessScore(right) * 1000 +
      (rightId && rightId === context.ownerId ? 100 : 0) +
      (rightId && rightId === context.createdBy ? 80 : 0) +
      (rightId && companyUserIds.has(rightId) ? 40 : 0) +
      (roleByUserId.get(rightId) || 0) * 5;
    return rightPriority - leftPriority;
  });

  return ranked[0] || null;
}

/* `cache` porque a pagina chama isto duas vezes por acesso, uma no titulo e
   outra no corpo, e ela e dinamica: sem isto, cada visita roda o conjunto de
   sete consultas em dobro. */
const fetchPublicPurchase = cache(async function fetchPublicPurchase(
  token: string
): Promise<PublicPurchasePayload | null> {
  const lido = verifySupplierPurchaseOrderPublicToken(token);
  if (!lido.ok) return null;

  const admin = createAdminClient();

  const { data: purchase } = await admin
    .from("supplier_purchase_orders")
    .select(
      "id,company_id,supplier_id,created_by,order_number,description,total_amount,shipping_amount,discount_amount,tax_amount,status,ordered_at,expected_at,notes,created_at,public_link_version"
    )
    .eq("id", lido.pedido.purchaseOrderId)
    .maybeSingle();

  if (!purchase?.id) return null;

  /* O link carrega a versao com que foi assinado. Se o comprador gerou um link
     novo, a versao da compra subiu e o endereco antigo para de abrir aqui. */
  const versaoGravada = Math.max(1, Number(purchase.public_link_version ?? 1));
  if (lido.pedido.linkVersion !== versaoGravada) return null;

  const [{ data: supplier }, { data: items }, { data: company }, { data: companyUsers }] = await Promise.all([
    admin
      .from("suppliers")
      .select("id,name,cnpj,email,phone")
      .eq("id", purchase.supplier_id)
      .eq("company_id", purchase.company_id)
      .is("deleted_at", null)
      .maybeSingle(),
    admin
      .from("supplier_purchase_order_items")
      .select("id,material_name,unit,quantity,unit_price,total_price,notes")
      .eq("purchase_order_id", purchase.id)
      .eq("company_id", purchase.company_id)
      .eq("supplier_id", purchase.supplier_id)
      .order("created_at", { ascending: true }),
    admin
      .from("companies")
      .select("owner_id")
      .eq("id", purchase.company_id)
      .maybeSingle(),
    admin
      .from("company_users")
      .select("user_id,role")
      .eq("company_id", purchase.company_id),
  ]);

  /* `sessionUserId` estava nesta lista, com peso alto no desempate.
     Consequencia: um usuario logado da empresa B que abrisse o link de um
     pedido da empresa A via o nome, o CNPJ, o telefone, o e-mail, o endereco e
     o logotipo da propria empresa impressos no documento da outra. O documento
     mudava de identidade conforme quem abria. O comprador de um pedido e
     sempre a empresa dona da compra, e ponto. */
  const profileCandidates = Array.from(
    new Set(
      [
        typeof purchase?.created_by === "string" ? purchase.created_by : "",
        typeof company?.owner_id === "string" ? company.owner_id : "",
        ...((companyUsers || []).map((item) => (typeof item?.user_id === "string" ? item.user_id : ""))),
        purchase.company_id,
      ].filter(Boolean)
    )
  );

  let profile: ProfileRow | null = null;
  let payable: PublicPurchasePayload["payable"] = null;
  if (profileCandidates.length > 0) {
    const { data: profileRows } = await admin
      .from("profiles")
      .select(
        "id,catalog_name,store_name,logo_url,catalog_logo_url,cnpj,company_phone,phone,company_email,address,address_zip,address_street,address_number,address_complement,address_neighborhood,address_city,address_state"
      )
      .in("id", profileCandidates);

    const rows = (profileRows || []) as ProfileRow[];
    profile =
      pickBestCompanyProfile(rows, {
        createdBy: purchase?.created_by || null,
        ownerId: typeof company?.owner_id === "string" ? company.owner_id : null,
        companyUsers: (companyUsers || []) as CompanyUserRow[],
      }) ||
      rows.find((row) => row.id === purchase.company_id) ||
      rows[0] ||
      null;
  }

  const payableSelection = async (columns: string[]) =>
    admin
      .from("accounts_payable")
      .select(columns.join(","))
      .eq("company_id", purchase.company_id)
      .eq("purchase_order_id", purchase.id)
      .limit(1)
      .maybeSingle();

  const primaryPayable = await payableSelection(["payment_method", "payment_date", "due_date", "status"]);
  if (!primaryPayable.error) {
    payable = (primaryPayable.data as PublicPurchasePayload["payable"]) ?? null;
  } else {
    const fallbackPayable = await payableSelection(["payment_date", "due_date", "status"]);
    if (!fallbackPayable.error) {
      payable = fallbackPayable.data
        ? ({
            payment_method: null,
            payment_date: (fallbackPayable.data as { payment_date?: string | null }).payment_date ?? null,
            due_date: (fallbackPayable.data as { due_date?: string | null }).due_date ?? null,
            status: (fallbackPayable.data as { status?: string | null }).status ?? null,
          } satisfies NonNullable<PublicPurchasePayload["payable"]>)
        : null;
    }
  }

  return {
    purchase: purchase as PurchaseRow,
    supplier: supplier as SupplierRow | null,
    items: (items || []) as PurchaseItemRow[],
    profile,
    payable,
  };
});

export async function generateMetadata(props: PublicPurchasePageProps): Promise<Metadata> {
  const params = await props.params;
  const data = await fetchPublicPurchase(params.token);
  const orderNumber = data?.purchase.order_number ? `#${data.purchase.order_number}` : "";
  const supplierName = data?.supplier?.name || "Fornecedor";
  return {
    title: `Pedido de compra ${orderNumber} - ${supplierName}`,
    description: "Comprovante publico de pedido de compra com itens, quantidades e valores negociados.",
    /* O documento tem CNPJ, endereco e precos negociados. Se o link cair numa
       pagina publica ou numa extensao de navegador, nao pode virar resultado
       de busca. */
    robots: { index: false, follow: false },
  };
}

export default async function PublicSupplierPurchaseOrderPage(props: PublicPurchasePageProps) {
  const params = await props.params;
  const searchParams = await props.searchParams;
  const data = await fetchPublicPurchase(params.token);
  if (!data) notFound();

  const printMode = searchParams.print === "1";
  const companyName = resolveProfileName(data.profile);
  const companyLogo = data.profile?.logo_url || data.profile?.catalog_logo_url || "";
  const companyPhone = data.profile?.company_phone || data.profile?.phone || "";
  const companyEmail = data.profile?.company_email || "";
  const companyAddress = buildAddress(data.profile);
  const itemCount = data.items.length;
  const issuedAt = data.purchase.created_at || data.purchase.ordered_at || null;
  const hasNotes = hasValue(data.purchase.notes);
  const subtotal = data.items.reduce((sum, item) => sum + Number(item.total_price || 0), 0);
  /* Frete, imposto e desconto sao do pedido inteiro, e nao de um item. O
     fornecedor precisa ver os tres discriminados: e o documento que ele vai
     conferir contra a nota que emitir. */
  const frete = Number(data.purchase.shipping_amount || 0);
  const imposto = Number(data.purchase.tax_amount || 0);
  const desconto = Number(data.purchase.discount_amount || 0);
  const negotiatedAt = data.purchase.ordered_at || issuedAt;
  const paymentCondition = paymentMethodLabel(data.payable?.payment_method);

  return (
    <main className="min-h-screen bg-stone-100 px-4 py-8 text-slate-900 print:bg-white print:px-0 print:py-0">
      <PrintTrigger enabled={printMode} />
      <style>{`
        @page {
          size: A4;
          margin: 10mm;
        }
        .purchase-page {
          width: 210mm;
          min-height: 297mm;
        }
        @media print {
          html, body {
            background: #fff;
          }
          .purchase-page {
            width: 210mm;
            min-height: 297mm;
          }
          .purchase-header-meta {
            display: grid !important;
            grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
            gap: 6px 24px !important;
          }
          .purchase-party-grid {
            display: grid !important;
            grid-template-columns: 1fr 1fr 220px !important;
            gap: 16px !important;
          }
        }
      `}</style>

      <div className="purchase-page mx-auto max-w-full bg-white shadow-[0_10px_32px_rgba(15,23,42,0.08)] print:max-w-none print:shadow-none">
        <div className="border-b border-slate-300 px-6 py-4 print:hidden">
          <div className="flex items-center justify-end">
            <div className="flex flex-wrap items-center gap-2">
              <Link
                href={`/pedido-compra/${encodeURIComponent(params.token)}?print=1`}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center gap-2 border border-slate-300 px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-50"
              >
                <Download className="h-4 w-4" />
                Salvar em PDF
              </Link>
            </div>
          </div>
        </div>

        <div className="px-8 py-7 print:px-8 print:py-6">
          <header className="border-b border-slate-300 pb-4">
            <div className="flex items-end justify-between gap-6">
              <div>
                <div className="text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-500">Pedido de compra</div>
                <div className="mt-1 text-[24px] font-semibold leading-none tracking-[-0.02em] text-slate-950">
                  #{data.purchase.order_number || "-"}
                </div>
              </div>
              <div className="purchase-header-meta grid shrink-0 gap-x-6 gap-y-1 text-[11px] text-slate-600 sm:grid-cols-2 lg:grid-cols-4">
                <div className="flex items-center justify-between gap-3 sm:min-w-[120px]">
                  <span>Emissão</span>
                  <span className="font-medium text-slate-900">{formatDate(issuedAt)}</span>
                </div>
                <div className="flex items-center justify-between gap-3 sm:min-w-[120px]">
                  <span>Pedido</span>
                  <span className="font-medium text-slate-900">{formatDate(data.purchase.ordered_at)}</span>
                </div>
                <div className="flex items-center justify-between gap-3 sm:min-w-[120px]">
                  <span>Previsão</span>
                  <span className="font-medium text-slate-900">{formatDate(data.purchase.expected_at)}</span>
                </div>
                <div className="flex items-center justify-between gap-3 sm:min-w-[120px]">
                  <span>Status</span>
                  <span className="font-medium text-slate-900">{statusLabel(data.purchase.status)}</span>
                </div>
              </div>
            </div>
          </header>

          <section className="border-b border-slate-300 py-4">
            <div className="purchase-party-grid grid gap-4 md:grid-cols-[1fr_1fr_220px]">
              <div className="min-w-0">
                <div className="text-[9px] font-semibold uppercase tracking-[0.16em] text-slate-500">Comprador</div>
                <div className="mt-1 flex min-w-0 items-start gap-3">
                  {companyLogo ? (
                    <div className="shrink-0 border border-slate-200 p-1">
                      <Image src={companyLogo} alt={companyName} width={36} height={36} className="h-[28px] w-[28px] object-contain" />
                    </div>
                  ) : null}
                  <div className="min-w-0">
                    <div className="text-[13px] font-semibold leading-tight text-slate-950">{companyName}</div>
                    <div className="mt-1 space-y-0.5 text-[10px] leading-snug text-slate-600">
                      {hasValue(data.profile?.cnpj) ? <div>CNPJ {formatDocument(data.profile?.cnpj)}</div> : null}
                      {hasValue(companyPhone) ? <div>{companyPhone}</div> : null}
                      {hasValue(companyEmail) ? <div>{companyEmail}</div> : null}
                      {hasValue(companyAddress) ? <div>{companyAddress}</div> : null}
                    </div>
                  </div>
                </div>
              </div>

              <div className="min-w-0">
                <div className="text-[9px] font-semibold uppercase tracking-[0.16em] text-slate-500">Fornecedor</div>
                <div className="mt-1 text-[13px] font-semibold leading-tight text-slate-950">
                  {data.supplier?.name || "Fornecedor"}
                </div>
                <div className="mt-1 space-y-0.5 text-[10px] leading-snug text-slate-600">
                  <div>Documento {formatDocument(data.supplier?.cnpj)}</div>
                  <div>{data.supplier?.phone || "-"}</div>
                  <div>{data.supplier?.email || "-"}</div>
                </div>
              </div>

              <div className="min-w-0 border-l border-slate-200 pl-4">
                <div className="text-[9px] font-semibold uppercase tracking-[0.16em] text-slate-500">Resumo</div>
                <div className="mt-1 text-[12px] font-semibold leading-tight text-slate-950">
                  {data.purchase.description || "Pedido de compra"}
                </div>
                <div className="mt-2 space-y-1 text-[10px] leading-4 text-slate-600">
                  <div className="flex items-center justify-between gap-3">
                    <span>Itens</span>
                    <span className="font-medium text-slate-900">{itemCount}</span>
                  </div>
                  <div className="flex items-center justify-between gap-3">
                    <span>Total</span>
                    <span className="font-semibold text-slate-950">{formatMoney(data.purchase.total_amount)}</span>
                  </div>
                </div>
              </div>
            </div>
          </section>

          <section className="py-4">
            <div className="mb-2 border-b border-slate-300 pb-2 text-center">
              <div className="text-[11px] text-slate-500">
                Valores negociados em: {formatDate(negotiatedAt)} | Condicao de pagamento: {paymentCondition}
              </div>
            </div>

            <div className="overflow-x-auto">
              <table className="min-w-full border-collapse text-[12px] leading-5">
                <thead>
                  <tr className="border-b border-slate-300 text-left text-[10px] font-semibold uppercase tracking-[0.14em] text-slate-500">
                    <th className="py-2 pr-3">Item</th>
                    <th className="py-2 px-3">Un.</th>
                    <th className="py-2 px-3 text-right">Qtd.</th>
                    <th className="py-2 px-3 text-right">Valor unit.</th>
                    <th className="py-2 px-3 text-right">Total</th>
                    <th className="py-2 pl-3">Observação</th>
                  </tr>
                </thead>
                <tbody>
                  {data.items.map((item) => (
                    <tr key={item.id} className="border-b border-slate-200 align-top">
                      <td className="py-2 pr-3 font-medium text-slate-950">{item.material_name || "Item"}</td>
                      <td className="px-3 py-2 text-slate-700">{item.unit || "-"}</td>
                      <td className="px-3 py-2 text-right text-slate-700">{formatQuantity(item.quantity)}</td>
                      <td className="px-3 py-2 text-right text-slate-700">{formatMoney(item.unit_price)}</td>
                      <td className="px-3 py-2 text-right font-semibold text-slate-950">{formatMoney(item.total_price)}</td>
                      <td className="py-2 pl-3 text-slate-600">{item.notes || "-"}</td>
                    </tr>
                  ))}
                  {data.items.length === 0 ? (
                    <tr>
                      <td colSpan={6} className="py-8 text-center text-[12px] text-slate-500">
                        Nenhum item encontrado.
                      </td>
                    </tr>
                  ) : null}
                </tbody>
              </table>
            </div>
          </section>

          {hasNotes ? (
            <section className="border-t border-slate-300 py-4">
              <div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500">Observações</div>
              <div className="mt-1 whitespace-pre-wrap text-[11px] leading-5 text-slate-700">{data.purchase.notes}</div>
            </section>
          ) : null}

          <footer className="border-t border-slate-300 pt-4">
            <div className="ml-auto w-full max-w-[320px]">
              <div className="space-y-1.5 text-[11px] text-slate-600">
                <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                  <span>Itens</span>
                  <span className="font-medium text-slate-900">{itemCount}</span>
                </div>
                <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                  <span>Subtotal</span>
                  <span className="font-medium text-slate-900">{formatMoney(subtotal)}</span>
                </div>
                {frete > 0 ? (
                  <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                    <span>Frete</span>
                    <span className="font-medium text-slate-900">{formatMoney(frete)}</span>
                  </div>
                ) : null}
                {imposto > 0 ? (
                  <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                    <span>Imposto</span>
                    <span className="font-medium text-slate-900">{formatMoney(imposto)}</span>
                  </div>
                ) : null}
                {desconto > 0 ? (
                  <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                    <span>Desconto</span>
                    <span className="font-medium text-slate-900">- {formatMoney(desconto)}</span>
                  </div>
                ) : null}
                <div className="flex items-center justify-between gap-4 border-b border-slate-200 pb-1">
                  <span>Status</span>
                  <span className="font-medium text-slate-900">{statusLabel(data.purchase.status)}</span>
                </div>
                <div className="flex items-center justify-between gap-4 pt-1 text-[15px] font-semibold text-slate-950">
                  <span>Total do pedido</span>
                  <span>{formatMoney(data.purchase.total_amount)}</span>
                </div>
              </div>
            </div>
          </footer>
        </div>
      </div>
    </main>
  );
}
