"use server";

import { ipDoCliente } from "@/lib/http/ip-do-cliente";
import { supportWriteError } from "@/lib/impersonate/support";
import { headers } from "next/headers";
import { revalidatePath } from "next/cache";
import { z } from "zod";

import { audit } from "@/lib/audit";
import { loadAuthUser, mfaEmDivida, resolveActiveOrg } from "@/lib/auth/server";
import { podeAdministrarEmpresa } from "@/lib/auth/pode-administrar-empresa";
import { createAdminClient } from "@/lib/supabase/admin";
import { MODOS_DE_VALOR_DA_VENDA, VALORES_DE_CATEGORIA } from "@/lib/conversoes/regras-google";

/**
 * Salva PARA ONDE o Google Ads reporta — a conta e a ação de conversão.
 *
 * Irmã de `updateAdPlatformConnection.ts` (a da Meta), separada porque o
 * refresh token não entra aqui: ele chega pelo fluxo OAuth
 * (`/api/v1/plataformas-de-anuncio/google/connect` → `.../callback`), que é a
 * ÚNICA porta de escrita dele. Esta action só grava os três identificadores
 * que o OAuth não descobre sozinho — ver o cabeçalho da migration 0307 — e o
 * interruptor de habilitado, mesmo par admin+MFA da irmã.
 */
export type UpdateGoogleAdsConnectionResult =
  | { ok: true }
  | {
      ok: false;
      error:
        | "validation_failed"
        | "unauthenticated"
        | "forbidden_tenant"
        | "forbidden_role"
        | "mfa_required"
        | "erro_ao_gravar";
      details?: unknown;
    };

const entradaSchema = z.object({
  customer_id: z
    .string()
    .trim()
    .transform((v) => v.replace(/\D/g, ""))
    .pipe(z.string().length(10, "precisa ter 10 dígitos")),
  login_customer_id: z
    .string()
    .trim()
    .transform((v) => v.replace(/\D/g, ""))
    .pipe(z.union([z.literal(""), z.string().length(10)]))
    .nullable()
    .optional(),
  // Vazio = a organização não reporta a compra, só etapas (0436).
  conversion_action_id: z
    .string()
    .trim()
    .max(32)
    .regex(/^\d*$/, "só dígitos")
    .transform((v) => v || null),
  enabled: z.boolean(),
  purchase_value_mode: z.enum(MODOS_DE_VALOR_DA_VENDA).optional(),
  purchase_category: z.enum(VALORES_DE_CATEGORIA).optional(),
  send_hashed_phone: z.boolean().optional(),
});

export type GoogleAdsConnectionInput = z.input<typeof entradaSchema>;

export async function updateGoogleAdsConnection(
  input: GoogleAdsConnectionInput,
): Promise<UpdateGoogleAdsConnectionResult> {
  const parsed = entradaSchema.safeParse(input);
  if (!parsed.success) {
    return { ok: false, error: "validation_failed", details: parsed.error.flatten() };
  }

  const authUser = await loadAuthUser();
  if (!authUser) return { ok: false, error: "unauthenticated" };
  if (supportWriteError(authUser.support)) return { ok: false, error: "forbidden_role" };
  const activeOrg = await resolveActiveOrg(authUser);
  if (!activeOrg) return { ok: false, error: "forbidden_tenant" };
  if (!podeAdministrarEmpresa(authUser, activeOrg)) {
    return { ok: false, error: "forbidden_role" };
  }
  if (await mfaEmDivida()) return { ok: false, error: "mfa_required" };

  const admin = createAdminClient();

  // A qualificação de etapa única (0402) virou regra por etapa (0436):
  // `salvarRegrasDeConversaoGoogle`. Esta action cuida só da conta e da venda.

  const loginCustomerId = parsed.data.login_customer_id?.trim() || null;

  // `update`, não `upsert`: a linha só existe depois do OAuth (a rota de
  // callback já fez o upsert com o refresh token). Chegar aqui sem linha é
  // tentar configurar uma conexão que nunca foi autorizada, e um `upsert`
  // criaria uma linha `enabled=true` sem refresh token nenhum — exatamente o
  // estado "conectada e não funciona" que a tela existe para não permitir.
  const { data, error } = await admin
    .from("ad_platform_connections")
    .update({
      google_customer_id: parsed.data.customer_id,
      google_login_customer_id: loginCustomerId,
      google_conversion_action_id: parsed.data.conversion_action_id,
      enabled: parsed.data.enabled,
      ...(parsed.data.purchase_value_mode
        ? { google_purchase_value_mode: parsed.data.purchase_value_mode }
        : {}),
      ...(parsed.data.purchase_category
        ? { google_purchase_category: parsed.data.purchase_category }
        : {}),
      ...(parsed.data.send_hashed_phone !== undefined
        ? { google_send_hashed_phone: parsed.data.send_hashed_phone }
        : {}),
      updated_by: authUser.id,
    })
    .eq("organization_id", activeOrg.orgId)
    .eq("platform", "google_ads")
    .select("id");

  if (error) return { ok: false, error: "erro_ao_gravar", details: error.message };
  // A CATRACA DA ISSUE #144: `update` sem `.select()` devolve sucesso mesmo
  // casando ZERO linhas. Sem conexão OAuth ainda, `data` vem vazio — e é
  // exatamente o caso "autorize o Google primeiro" que a tela precisa dizer.
  if (!data || data.length === 0) {
    return { ok: false, error: "erro_ao_gravar", details: "conecte com o Google primeiro" };
  }

  const hdrs = await headers();
  await audit({
    action: "ad_platform_connection.updated",
    actorUserId: authUser.id,
    organizationId: activeOrg.orgId,
    resourceType: "ad_platform_connections",
    resourceId: null,
    requestId: hdrs.get("x-request-id") ?? undefined,
    ip: ipDoCliente(hdrs) ?? undefined,
    userAgent: hdrs.get("user-agent") ?? undefined,
    metadata: {
      platform: "google_ads",
      enabled: parsed.data.enabled,
      customer_id: parsed.data.customer_id,
      tem_login_customer_id: Boolean(loginCustomerId),
      tem_acao_de_venda: Boolean(parsed.data.conversion_action_id),
      ...(parsed.data.purchase_value_mode
        ? { purchase_value_mode: parsed.data.purchase_value_mode }
        : {}),
      ...(parsed.data.send_hashed_phone !== undefined
        ? { send_hashed_phone: parsed.data.send_hashed_phone }
        : {}),
    },
  });

  revalidatePath("/app/settings/conversoes");
  return { ok: true };
}
