// Configuration des integrations Google (Search Console + GA4 + PageSpeed).
//
// Un seul service account Google Cloud cote Novelia interroge GSC + GA4 sur
// TOUS les sites clients. Le client ajoute simplement l'email du service account
// comme utilisateur dans sa propriete GSC et son acces GA4 lors de l'onboarding.
//
// On utilise les packages scopes @googleapis/* (un par API) plutot que le
// gros package `googleapis` complet, pour reduire drastiquement le poids
// du bundle standalone (~50 MB economises).

import "server-only";
import { JWT } from "google-auth-library";
import { searchconsole_v1, auth as searchAuth } from "@googleapis/searchconsole";
import { analyticsdata_v1beta } from "@googleapis/analyticsdata";
import { pagespeedonline_v5 } from "@googleapis/pagespeedonline";

type ServiceAccountKey = {
  type: string;
  project_id: string;
  private_key_id: string;
  private_key: string;
  client_email: string;
  client_id?: string;
};

let cachedAuth: JWT | null = null;
let cachedCredentials: ServiceAccountKey | null = null;

function parseCredentials(): ServiceAccountKey | null {
  if (cachedCredentials) return cachedCredentials;

  // Source 1 : fichier sur disque (GOOGLE_APPLICATION_CREDENTIALS, standard GCP).
  // En prod on monte /app/google-sa.json via docker-compose.
  const filePath = process.env.GOOGLE_APPLICATION_CREDENTIALS?.trim();
  if (filePath) {
    try {
      // Import dynamique node:fs : evite de charger le module dans des contextes edge.
      const fs = require("node:fs") as typeof import("node:fs");
      const raw = fs.readFileSync(filePath, "utf8");
      const parsed = JSON.parse(raw) as ServiceAccountKey;
      if (!parsed.client_email || !parsed.private_key) {
        console.warn(`[google] ${filePath} manque client_email ou private_key`);
        return null;
      }
      cachedCredentials = parsed;
      return parsed;
    } catch (err) {
      console.error(`[google] Lecture de ${filePath} echouee :`, err);
      // On tente la source 2 plutot que d'echouer dur.
    }
  }

  // Source 2 : JSON stringifie dans l'env.
  const raw = process.env.GOOGLE_SERVICE_ACCOUNT_KEY_JSON?.trim();
  if (!raw) return null;

  try {
    const parsed = JSON.parse(raw) as ServiceAccountKey;
    if (!parsed.client_email || !parsed.private_key) {
      console.warn("[google] GOOGLE_SERVICE_ACCOUNT_KEY_JSON manque client_email ou private_key");
      return null;
    }
    cachedCredentials = parsed;
    return parsed;
  } catch (err) {
    console.error("[google] GOOGLE_SERVICE_ACCOUNT_KEY_JSON invalide :", err);
    return null;
  }
}

// Email du service account, derive de la cle ou fallback sur GOOGLE_SERVICE_ACCOUNT_EMAIL.
export function getServiceAccountEmail(): string | null {
  const creds = parseCredentials();
  if (creds?.client_email) return creds.client_email;
  const fallback = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL?.trim();
  return fallback && fallback.length > 0 ? fallback : null;
}

// True si une source d'identification est disponible (OAuth admin OU service account).
export async function hasGoogleCredentials(): Promise<boolean> {
  if (parseCredentials() !== null) return true;
  // OAuth ?
  try {
    const { getOauthStatus } = await import("./google-oauth");
    const status = await getOauthStatus();
    return status.connected;
  } catch {
    return false;
  }
}

const SCOPES = [
  "https://www.googleapis.com/auth/webmasters.readonly",
  "https://www.googleapis.com/auth/analytics.readonly",
];

function getAuth(): JWT | null {
  if (cachedAuth) return cachedAuth;
  const creds = parseCredentials();
  if (!creds) return null;

  cachedAuth = new JWT({
    email: creds.client_email,
    key: creds.private_key,
    scopes: SCOPES,
  });
  return cachedAuth;
}

// === Clients APIs ===
// On essaie d'abord l'OAuth (compte personnel de l'admin) car le client n'a
// rien a faire (le compte est deja autorise sur les GSC/GA4 des clients).
// Fallback sur le service account si pas d'OAuth.

export async function getSearchConsoleClient() {
  // Import dynamique pour eviter le cycle d'import : google-oauth.ts importe
  // depuis lib/db qui peut importer indirectement google.ts.
  const { getOAuthSearchConsoleClient } = await import("./google-oauth");
  const oauthClient = await getOAuthSearchConsoleClient();
  if (oauthClient) return oauthClient;

  const auth = getAuth();
  if (!auth) return null;
  return new searchconsole_v1.Searchconsole({ auth });
}

export async function getAnalyticsDataClient() {
  const { getOAuthAnalyticsDataClient } = await import("./google-oauth");
  const oauthClient = await getOAuthAnalyticsDataClient();
  if (oauthClient) return oauthClient;

  const auth = getAuth();
  if (!auth) return null;
  return new analyticsdata_v1beta.Analyticsdata({ auth });
}

export function getPageSpeedClient() {
  // PageSpeed Insights : pas d'auth obligatoire (API publique), mais une cle augmente le quota.
  return new pagespeedonline_v5.Pagespeedonline({
    auth: process.env.PAGESPEED_API_KEY,
  });
}

// Re-export pour le type narrow dans les server actions.
export { searchAuth };

// Procedure que le client doit suivre une fois le service account ajoute par Novelia.
export const GOOGLE_ONBOARDING_STEPS = [
  {
    title: "Ajouter le service account dans Search Console",
    detail:
      "Search Console > Parametres > Utilisateurs et autorisations > Ajouter un utilisateur. Coller l'email du service account, role Proprietaire.",
  },
  {
    title: "Ajouter le service account dans Google Analytics 4",
    detail:
      "GA4 > Administration > Gestion des acces de la propriete > Ajouter. Coller l'email, role Analyste.",
  },
  {
    title: "Recuperer la Property ID GA4",
    detail:
      "GA4 > Administration > Details de la propriete. Copier le numero affiche (sans le prefixe properties/).",
  },
  {
    title: "Renseigner les identifiants ici",
    detail:
      "Coller l'URL de la propriete GSC (ex : sc-domain:cabinet-vidal.fr) et la Property ID GA4 dans le formulaire ci-dessous.",
  },
] as const;
