/**
 * GET /api/v1/voice/calls/history — histórico de chamadas da organização.
 *
 * Lê de `voice_calls` (a NOSSA cópia, sincronizada pela ponte de eventos do
 * worker — §4.2 da spec), não faz proxy pro `/history` do WaCalls: nossa
 * tabela já tem `contact_id`/`end_reason` que o upstream não devolve.
 */
import { randomUUID } from "node:crypto";
import { z } from "zod";

import { fail, ok } from "@/lib/api/wrappers";
import { logger } from "@/lib/logger";
import { requireRole } from "@/lib/auth/require-role";
import { createClient } from "@/lib/supabase/server";
import { idsDeContatosPessoais } from "@/app/api/v1/conversations/_handler";

export const dynamic = "force-dynamic";

export async function GET(req: Request): Promise<Response> {
  const requestId = randomUUID();

  const authz = await requireRole("agent", { requestId, resource: "voice_calls" });
  if (!authz.ok) return authz.response;
  const { org: activeOrg } = authz;

  const { searchParams } = new URL(req.url);
  const limit = Math.min(Number(searchParams.get("limit") ?? "50") || 50, 200);
  // `id`: o painel de chamada confere UMA ligação com o servidor. Procurá-la
  // entre as N mais recentes da organização falhava em escritório movimentado.
  const id = searchParams.get("id");
  if (id !== null && !z.string().uuid().safeParse(id).success) {
    return fail("invalid_request", "id precisa ser um uuid.", 400, { requestId });
  }

  const supabase = await createClient();
  let consulta = supabase
    .from("voice_calls")
    .select(
      "id, contact_id, direction, peer_phone, status, end_reason, started_at, answered_at, ended_at, duration_ms, owner_user_id, created_by",
    )
    .eq("organization_id", activeOrg.orgId);
  // Chamada de pessoal some do histórico e só volta ao desmarcar (spec 21,
  // etapa 14) — a mesma primitiva de ids da lista do inbox. Bloqueado continua
  // aparecendo (recusada); por isso o filtro é só de pessoal.
  const pessoais = await idsDeContatosPessoais(supabase, activeOrg.orgId);
  if (pessoais.length > 0) {
    consulta = consulta.not("contact_id", "in", `(${pessoais.join(",")})`);
  }
  if (id) consulta = consulta.eq("id", id);
  const { data, error } = await consulta.order("started_at", { ascending: false }).limit(limit);

  // ERRO NÃO É LISTA VAZIA.
  //
  // `ok([])` fazia "a consulta falhou" ficar indistinguível de "esta
  // organização nunca ligou para ninguém" — e a segunda frase é a que a tela
  // conta. Além de esconder a falha, é o desfecho que convida alguém a concluir
  // que o histórico se perdeu. Falhar ABERTO na informação, sempre.
  if (error) {
    logger.error("voice: histórico de chamadas falhou", {
      request_id: requestId,
      organization_id: activeOrg.orgId,
      error: error.message,
    });
    return fail("internal_error", error.message, 500, { requestId });
  }
  return ok(data ?? [], { requestId, meta: { has_more: (data?.length ?? 0) === limit } });
}
