import type { SupabaseClient } from "@supabase/supabase-js";

/*
  Chats Ktalogu, lado do cliente.

  Mesmas tabelas que a loja usa no admin (chat_threads e chat_messages): o fio e
  um so, visto de duas portas. Aqui ficam apenas as funcoes de que o portal
  precisa — o cliente nunca lista conversas de outra gente.
*/

type Admin = SupabaseClient;

export const BUCKET_DA_CONVERSA = "quote-arts";
/* Anexo novo mora aqui, numa pasta PRIVADA (migration 161). So sai por
   /api/conversa/anexo/<mensagem>, que confere quem pede e assina na hora.
   `quote-arts` continua so para os anexos antigos. */
export const BUCKET_PRIVADO_DA_CONVERSA = "conversas";
export const TAMANHO_MAXIMO_DO_ANEXO = 8 * 1024 * 1024;

const CAMPOS_DA_MENSAGEM =
  "id,thread_id,author_type,author_name,body,attachment_url,attachment_path,attachment_name,attachment_kind,card,is_art,art_status,art_decided_at,art_decision_note,created_at,deleted_at,read_by_store_at,read_by_other_at";

type MensagemDoBanco = {
  id: string;
  author_type: string;
  author_name?: string | null;
  body?: string | null;
  attachment_url?: string | null;
  attachment_path?: string | null;
  attachment_name?: string | null;
  attachment_kind?: string | null;
  card?: Record<string, unknown> | null;
  is_art?: boolean | null;
  art_status?: string | null;
  art_decided_at?: string | null;
  art_decision_note?: string | null;
  created_at: string;
  deleted_at?: string | null;
  read_by_store_at?: string | null;
  read_by_other_at?: string | null;
};

/* O endereco que a tela usa para abrir o anexo. O novo passa pela rota que
   confere quem pede; o antigo segue com o endereco publico que ja tinha. */
export function enderecoDoAnexo(mensagem: { id: string; attachment_path?: string | null; attachment_url?: string | null }) {
  if (mensagem.attachment_path) return `/api/conversa/anexo/${mensagem.id}`;
  return mensagem.attachment_url || null;
}

/* A tela ja fala "sender" e "read_by_client_at": a traducao mora aqui, e nao no
   componente. */
export function mensagemParaTela(mensagem: MensagemDoBanco) {
  const apagada = Boolean(mensagem.deleted_at);
  return {
    id: mensagem.id,
    sender: mensagem.author_type === "client" ? "client" : "store",
    sender_name: mensagem.author_name || null,
    body: apagada ? null : mensagem.body || null,
    attachment_url: apagada ? null : enderecoDoAnexo(mensagem),
    attachment_name: apagada ? null : mensagem.attachment_name || null,
    attachment_kind: apagada ? null : mensagem.attachment_kind || null,
    card: apagada ? null : mensagem.card || null,
    is_art: apagada ? false : Boolean(mensagem.is_art),
    art_status: apagada ? null : mensagem.art_status || null,
    art_decided_at: mensagem.art_decided_at || null,
    art_decision_note: apagada ? null : mensagem.art_decision_note || null,
    created_at: mensagem.created_at,
    deleted_at: mensagem.deleted_at || null,
    read_by_store_at: mensagem.read_by_store_at || null,
    read_by_client_at: mensagem.read_by_other_at || null,
  };
}

export async function conversaDoPedido(
  admin: Admin,
  pedido: { id: string; user_id: string; number?: number | null; client_id?: string | null }
) {
  const { data: existente } = await admin
    .from("chat_threads")
    .select("id")
    .eq("kind", "order")
    .eq("order_id", pedido.id)
    .maybeSingle();

  if (existente?.id) return existente as { id: string };

  const { data: criada, error } = await admin
    .from("chat_threads")
    .insert({
      user_id: pedido.user_id,
      kind: "order",
      order_id: pedido.id,
      client_id: pedido.client_id || null,
      title: pedido.number ? `Pedido #${pedido.number}` : "Pedido",
    })
    .select("id")
    .single();

  if (error) {
    const { data: depois } = await admin
      .from("chat_threads")
      .select("id")
      .eq("kind", "order")
      .eq("order_id", pedido.id)
      .maybeSingle();
    if (depois?.id) return depois as { id: string };
    throw new Error(error.message);
  }

  return criada as { id: string };
}

export async function listarMensagensDaConversa(admin: Admin, threadId: string, limite = 200) {
  const { data, error } = await admin
    .from("chat_messages")
    .select(CAMPOS_DA_MENSAGEM)
    .eq("thread_id", threadId)
    /* O recado interno da equipe nunca sai daqui. E a linha que separa "anotei
       para nao esquecer" de "mandei para o cliente sem querer". */
    .eq("internal", false)
    .order("created_at", { ascending: false })
    .limit(limite);

  if (error) throw new Error(error.message);
  return ((data || []) as MensagemDoBanco[]).slice().reverse();
}

export async function marcarConversaComoLidaPeloCliente(admin: Admin, threadId: string) {
  const agora = new Date().toISOString();
  await admin
    .from("chat_messages")
    .update({ read_by_other_at: agora })
    .eq("thread_id", threadId)
    .in("author_type", ["store", "team", "system"])
    .is("read_by_other_at", null);

  await admin.from("chat_threads").update({ unread_other: 0 }).eq("id", threadId);
}

export async function atualizarResumoDaConversa(
  admin: Admin,
  threadId: string,
  mensagem: { body?: string | null; attachment_kind?: string | null; created_at?: string }
) {
  const { data: atual } = await admin
    .from("chat_threads")
    .select("unread_store")
    .eq("id", threadId)
    .maybeSingle();

  const corpo = String(mensagem.body || "").trim();
  const resumo = corpo || (mensagem.attachment_kind === "image" ? "Imagem" : mensagem.attachment_kind ? "Arquivo" : "");

  await admin
    .from("chat_threads")
    .update({
      last_message_at: mensagem.created_at || new Date().toISOString(),
      last_message_preview: resumo.slice(0, 120) || null,
      last_message_author: "client",
      updated_at: new Date().toISOString(),
      unread_store: Number(atual?.unread_store || 0) + 1,
    })
    .eq("id", threadId);
}
