import { getSupabaseClient } from "@/lib/supabase";
import type { DocumentoDoBanner } from "./documento";

/*
 * As provas da arte para o cliente aprovar (migration 224, provas_de_arte):
 * cada prova congela a arte como estava (todas as páginas) e tem um link
 * público (/prova/<token>) em que o cliente aprova ou pede alteração. A
 * leitura e a resposta pelo link vão por duas funções do banco que só fazem
 * isso (ver_prova_da_arte e responder_prova_da_arte).
 */

/* `no_orcamento`: a resposta entrou na arte do item do orçamento (migration 232): o sino avisa por lá. */
export type RespostaDaProva = { quando: string; situacao: "aprovada" | "alteracao"; nome: string; comentario: string; no_orcamento?: boolean };
export type ResumoDaProva = { id: string; token: string; nome: string; situacao: "aguardando" | "aprovada" | "alteracao"; respostas: RespostaDaProva[]; created_at: string; quote_id: string | null; order_id: string | null; ativa: boolean; quote_item_id?: string | null };

export class ProvasIndisponiveis extends Error {}

function faltaATabela(erro: { code?: string; message?: string } | null) {
  return Boolean(erro && (erro.code === "42P01" || erro.code === "PGRST205" || erro.code === "PGRST202" || /provas_de_arte/.test(erro.message || "")));
}

export async function listarProvas(arteId: string): Promise<ResumoDaProva[]> {
  const { data, error } = await getSupabaseClient().from("provas_de_arte").select("id,token,nome,situacao,respostas,created_at,quote_id,order_id,ativa").eq("arte_id", arteId).order("created_at", { ascending: false }).limit(20);
  if (faltaATabela(error)) throw new ProvasIndisponiveis("A aprovação pelo link ainda não está ligada.");
  if (error) throw new Error("Não deu para abrir as aprovações.");
  return (data || []) as ResumoDaProva[];
}

/* A coluna do item ainda não existe (migration 232 não aplicada): a prova nasce sem ela. */
function faltaOItem(erro: { code?: string; message?: string } | null) {
  return Boolean(erro && (erro.code === "42703" || erro.code === "PGRST204" || /quote_item_id/.test(erro.message || "")));
}

export async function criarProva(dono: string, prova: { arteId: string | null; nome: string; documento: DocumentoDoBanner; quoteId?: string | null; orderId?: string | null; quoteItemId?: string | null }): Promise<ResumoDaProva> {
  const linha = { user_id: dono, arte_id: prova.arteId, nome: prova.nome.slice(0, 120) || "Arte", documento: prova.documento, quote_id: prova.quoteId || null, order_id: prova.orderId || null };
  const colunas = "id,token,nome,situacao,respostas,created_at,quote_id,order_id,ativa";
  let { data, error } = await getSupabaseClient()
    .from("provas_de_arte")
    .insert(prova.quoteItemId ? { ...linha, quote_item_id: prova.quoteItemId } : linha)
    .select(colunas)
    .single();
  if (prova.quoteItemId && faltaOItem(error)) ({ data, error } = await getSupabaseClient().from("provas_de_arte").insert(linha).select(colunas).single());
  if (faltaATabela(error)) throw new ProvasIndisponiveis("A aprovação pelo link ainda não está ligada.");
  if (error || !data) throw new Error("Não deu para criar o link de aprovação.");
  return data as ResumoDaProva;
}

export async function desativarProva(id: string) {
  const { error } = await getSupabaseClient().from("provas_de_arte").update({ ativa: false }).eq("id", id);
  if (error) throw new Error("Não deu para desativar o link.");
}

/** Os itens de um orçamento (a prova liga a um item: a resposta entra na arte dele). */
export async function itensDoOrcamento(orcamento: string): Promise<Array<{ id: string; titulo: string }>> {
  const { data } = await getSupabaseClient().from("quote_items").select("id,title,position").eq("quote_id", orcamento).order("position", { ascending: true });
  return ((data || []) as Array<{ id: string; title: string | null }>).map((i) => ({ id: i.id, titulo: i.title?.trim() || "Item sem nome" }));
}

/** As artes com a situação da prova mais nova de cada uma (para a galeria mostrar). */
export async function situacaoDasProvas(arteIds: string[]): Promise<Record<string, ResumoDaProva["situacao"]>> {
  if (!arteIds.length) return {};
  const { data, error } = await getSupabaseClient().from("provas_de_arte").select("arte_id,situacao,created_at").in("arte_id", arteIds.slice(0, 200)).eq("ativa", true).order("created_at", { ascending: false }).limit(400);
  if (error) return {};
  const mapa: Record<string, ResumoDaProva["situacao"]> = {};
  for (const p of (data || []) as Array<{ arte_id: string | null; situacao: ResumoDaProva["situacao"] }>) if (p.arte_id && !mapa[p.arte_id]) mapa[p.arte_id] = p.situacao;
  return mapa;
}

/** Os orçamentos e pedidos recentes da empresa, para ligar a prova a um deles. */
export async function orcamentosEPedidos(dono: string) {
  const supabase = getSupabaseClient();
  const [orcamentos, pedidos] = await Promise.all([
    supabase.from("quotes").select("id,number,title").eq("user_id", dono).order("created_at", { ascending: false }).limit(30),
    supabase.from("orders").select("id,number").eq("user_id", dono).order("created_at", { ascending: false }).limit(30),
  ]);
  return {
    orcamentos: ((orcamentos.data || []) as Array<{ id: string; number: number | string | null; title: string | null }>).map((o) => ({ id: o.id, rotulo: `Orçamento ${o.number ?? ""}${o.title ? ` · ${o.title}` : ""}`.trim() })),
    pedidos: ((pedidos.data || []) as Array<{ id: string; number: number | string | null }>).map((o) => ({ id: o.id, rotulo: `Pedido ${o.number ?? ""}`.trim() })),
  };
}

export function linkDaProva(token: string) {
  return `${window.location.origin}/prova/${token}`;
}
