// validate-telegram-bot
// Recebe { token } do usuário autenticado, valida no Telegram via getMe,
// garante unicidade do bot, salva o token no Vault e atualiza agent_instances.

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

interface GetMeResult {
  id: number;
  is_bot: boolean;
  first_name: string;
  username: string;
}

function jsonResponse(body: unknown, status = 200): Response {
  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 });
  }

  try {
    const supabaseUrl = Deno.env.get("SUPABASE_URL")!;
    const serviceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!;
    const anonKey = Deno.env.get("SUPABASE_ANON_KEY")!;

    const authHeader = req.headers.get("Authorization") ?? "";
    const userClient = createClient(supabaseUrl, anonKey, {
      global: { headers: { Authorization: authHeader } },
    });
    const { data: userData, error: userErr } = await userClient.auth.getUser();
    if (userErr || !userData.user) {
      return jsonResponse({ error: "Não autenticado" }, 401);
    }
    const userId = userData.user.id;

    const body = await req.json().catch(() => ({}));
    const token = (body?.token ?? "").toString().trim();
    if (!token || !/^\d+:[A-Za-z0-9_-]+$/.test(token)) {
      return jsonResponse(
        { error: "Token inválido. Verifique se copiou corretamente do BotFather." },
        400,
      );
    }

    // 1) Valida no Telegram
    const me = await telegramApi<GetMeResult>(token, "getMe");
    if (!me.ok) {
      if (me.status === 401 || me.status === 404) {
        return jsonResponse(
          { error: "Token inválido. Verifique se copiou corretamente do BotFather." },
          400,
        );
      }
      if (me.status === 429) {
        return jsonResponse(
          {
            error:
              "O Telegram está limitando nossas requisições. Aguarde 1 minuto e tente novamente.",
          },
          429,
        );
      }
      return jsonResponse(
        { error: me.description || "Falha ao validar token no Telegram." },
        502,
      );
    }

    const bot = me.result!;
    const botUsername = bot.username;
    const botName = bot.first_name;
    const botId = bot.id;

    // 2) Service-role client p/ banco e vault
    const admin = createClient(supabaseUrl, serviceKey);

    // 3) Garante que o usuário tem agent_instance
    const { data: agent, error: agentErr } = await admin
      .from("agent_instances")
      .select("id, telegram_bot_token_vault_id, status")
      .eq("user_id", userId)
      .maybeSingle();

    if (agentErr) {
      console.error("agent lookup error", agentErr);
      return jsonResponse({ error: "Falha ao localizar agente." }, 500);
    }
    if (!agent) {
      return jsonResponse(
        { error: "Seu agente ainda não está pronto. Aguarde o provisionamento." },
        409,
      );
    }
    if (agent.status === "suspended" || agent.status === "error") {
      return jsonResponse(
        { error: "Agente suspenso. Regularize sua assinatura antes de conectar o Telegram." },
        403,
      );
    }

    // 4) Verifica unicidade do bot username (em outro agent_instance)
    const { data: conflict } = await admin
      .from("agent_instances")
      .select("id")
      .eq("telegram_bot_username", botUsername)
      .neq("id", agent.id)
      .maybeSingle();

    if (conflict) {
      return jsonResponse(
        {
          error:
            "Este bot já está conectado a outra conta Mika. Crie um novo bot no BotFather.",
        },
        409,
      );
    }

    // 5) Se já houver um vault_id antigo, remove (reconexão)
    if (agent.telegram_bot_token_vault_id) {
      await admin.rpc("exec_sql_void", {}).catch(() => {});
      // tenta remover diretamente; ignora falha
      const { error: delErr } = await admin
        .from("vault.secrets" as unknown as never)
        .delete()
        .eq("id", agent.telegram_bot_token_vault_id);
      if (delErr) {
        console.warn("Vault old secret delete (ignorável):", delErr.message);
      }
    }

    // 6) Cria secret no Vault via RPC SQL
    const secretName = `telegram_bot_token_${userId}_${Math.floor(Date.now() / 1000)}`;
    const { data: vaultData, error: vaultErr } = await admin
      .rpc("vault_create_secret", {
        secret_value: token,
        secret_name: secretName,
        secret_description: `Telegram bot token for user ${userId}`,
      })
      .single();

    let secretId: string | null = null;
    if (!vaultErr && vaultData) {
      // RPC pode retornar { secret_id } ou string
      // deno-lint-ignore no-explicit-any
      secretId = (vaultData as any).secret_id ?? (vaultData as unknown as string);
    } else {
      // Fallback: usa SQL direto via PostgREST (requer função vault.create_secret exposta).
      // Caso não exista a RPC, criamos via PostgREST raw SQL exec.
      const sqlRes = await fetch(`${supabaseUrl}/rest/v1/rpc/vault_create_secret`, {
        method: "POST",
        headers: {
          apikey: serviceKey,
          Authorization: `Bearer ${serviceKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          secret_value: token,
          secret_name: secretName,
          secret_description: `Telegram bot token for user ${userId}`,
        }),
      });
      if (sqlRes.ok) {
        const out = await sqlRes.json().catch(() => null);
        secretId =
          (Array.isArray(out) ? out[0]?.secret_id ?? out[0] : out?.secret_id ?? out) ?? null;
      } else {
        console.error("vault_create_secret RPC failed", await sqlRes.text());
      }
    }

    if (!secretId) {
      return jsonResponse(
        {
          error:
            "Não foi possível salvar o token com segurança. Tente novamente em instantes.",
        },
        500,
      );
    }

    // 7) Atualiza agent_instances
    const { error: updErr } = await admin
      .from("agent_instances")
      .update({
        telegram_bot_token_vault_id: secretId,
        telegram_bot_username: botUsername,
        telegram_connected_at: new Date().toISOString(),
        telegram_token_invalid: false,
        telegram_webhook_configured: false,
        telegram_first_message_received_at: null,
        updated_at: new Date().toISOString(),
      })
      .eq("id", agent.id);

    if (updErr) {
      console.error("agent update error", updErr);
      return jsonResponse({ error: "Falha ao salvar dados do bot." }, 500);
    }

    return jsonResponse({
      valid: true,
      bot_username: botUsername,
      bot_name: botName,
      bot_id: botId,
    });
  } catch (err) {
    console.error("validate-telegram-bot fatal", err);
    return jsonResponse(
      { error: err instanceof Error ? err.message : "Erro inesperado" },
      500,
    );
  }
});
