// bootstrap-internal-secret
// Função one-shot: lê INTERNAL_FUNCTION_SECRET de env e persiste em vault como
// 'internal_function_secret', para que triggers pg_net e cron job possam ler e
// enviar como X-Internal-Secret nas chamadas a outras edge functions.
//
// Requer JWT de admin. Idempotente — pode ser chamada várias vezes.

import { createClient } from "https://esm.sh/@supabase/supabase-js@2.45.4";
import { corsHeaders } from "../_shared/cors.ts";

const SUPABASE_URL = Deno.env.get("SUPABASE_URL")!;
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
const SUPABASE_ANON_KEY = Deno.env.get("SUPABASE_ANON_KEY") ?? Deno.env.get("SUPABASE_PUBLISHABLE_KEY") ?? "";

function json(status: number, body: unknown) {
  return new Response(JSON.stringify(body), {
    status,
    headers: { ...corsHeaders, "Content-Type": "application/json" },
  });
}

Deno.serve(async (req) => {
  if (req.method === "OPTIONS") return new Response(null, { headers: corsHeaders });

  const secretValue = Deno.env.get("INTERNAL_FUNCTION_SECRET") ?? "";
  if (!secretValue) {
    return json(500, { error: "INTERNAL_FUNCTION_SECRET not set in env" });
  }

  // Validar admin via JWT
  const authHeader = req.headers.get("authorization") ?? "";
  if (!authHeader.toLowerCase().startsWith("bearer ")) {
    return json(401, { error: "missing bearer token" });
  }
  const userClient = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
    global: { headers: { Authorization: authHeader } },
    auth: { persistSession: false, autoRefreshToken: false },
  });
  const { data: userData, error: userErr } = await userClient.auth.getUser();
  if (userErr || !userData?.user) return json(401, { error: "invalid jwt" });

  const admin = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
    auth: { persistSession: false, autoRefreshToken: false },
  });
  const { data: roleOk } = await admin.rpc("has_role", {
    _user_id: userData.user.id,
    _role: "admin",
  });
  if (!roleOk) return json(403, { error: "admin role required" });

  // Upsert no vault. Como vault.create_secret falha em nomes duplicados,
  // tentamos atualizar existente primeiro via SQL direto.
  try {
    // 1) Tenta achar entry existente
    const { data: existing } = await admin
      .from("vault.decrypted_secrets" as never)
      .select("id, decrypted_secret")
      .eq("name", "internal_function_secret")
      .maybeSingle()
      .returns<{ id: string; decrypted_secret: string } | null>();

    if (existing && existing.decrypted_secret === secretValue) {
      return json(200, { ok: true, action: "already_synced" });
    }

    if (existing) {
      // Atualiza o valor via RPC dedicada (não temos UPDATE direto em vault.secrets via PostgREST,
      // então deletamos e recriamos).
      await admin.rpc("vault_delete_secret", { secret_id: existing.id });
    }

    const { data: created, error: createErr } = await admin
      .rpc("vault_create_secret", {
        secret_value: secretValue,
        secret_name: "internal_function_secret",
        secret_description: "Shared secret for trigger pg_net → edge functions auth",
      })
      .single();

    if (createErr) {
      console.error("vault_create_secret failed:", createErr);
      return json(500, { error: "vault create failed", detail: createErr.message });
    }

    return json(200, {
      ok: true,
      action: existing ? "rotated" : "created",
      // deno-lint-ignore no-explicit-any
      secret_id: (created as any)?.secret_id ?? created,
    });
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e);
    console.error("bootstrap-internal-secret fatal:", msg);
    return json(500, { error: msg });
  }
});
