/**
 * Google Business Profile Configuration Service
 *
 * Manages Google Business Profile OAuth settings stored in MongoDB.
 * The Client Secret is AES-256-GCM encrypted at rest.
 * Follows the same singleton pattern as N8nConfig (companyId: 'platform').
 *
 * When DB-stored credentials exist and are enabled, they take precedence
 * over env vars (GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URL).
 *
 * Provides:
 *   - getConfig(): Get current config (Client Secret masked — safe for frontend)
 *   - saveConfig(): Save/update Client ID, Client Secret, Redirect URI
 *   - deleteConfig(): Remove config (disables DB-based integration)
 *   - getCredentials(): Get decrypted credentials (for googleAuth service)
 *   - testConnection(): Validate the credentials by attempting a token request
 *   - toggleEnabled(): Enable/disable the integration
 */

import { encryptApiKey, decryptApiKey } from '../utils/encryption';
import { decryptGBPSecret } from '../../models/GoogleBusinessProfileConfig';

// ============================================
// GET CONFIG (Client Secret masked — safe for frontend)
// ============================================

export async function getGoogleBusinessProfileConfig(): Promise<{
  configured: boolean;
  enabled: boolean;
  clientId: string;
  clientSecretMasked?: string;
  redirectUri: string;
  status: string;
  lastValidatedAt?: string;
} | null> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  const config = await GoogleBusinessProfileConfig.findOne({ companyId: 'platform' })
    .select('+encryptedClientSecret +clientSecretIV');

  if (!config) {
    return {
      configured: false,
      enabled: false,
      clientId: '',
      redirectUri: '',
      status: 'disconnected',
    };
  }

  // Mask the Client Secret for frontend display
  let clientSecretMasked: string | undefined;
  if (config.encryptedClientSecret && config.clientSecretIV) {
    const fullSecret = decryptGBPSecret(config as any);
    if (fullSecret) {
      clientSecretMasked = fullSecret.length > 8
        ? `${fullSecret.slice(0, 4)}${'*'.repeat(Math.max(0, fullSecret.length - 8))}${fullSecret.slice(-4)}`
        : '••••••••';
    }
  }

  return {
    configured: true,
    enabled: config.enabled,
    clientId: config.clientId,
    clientSecretMasked,
    redirectUri: config.redirectUri,
    status: config.status,
    lastValidatedAt: config.lastValidatedAt?.toISOString(),
  };
}

// ============================================
// SAVE CONFIG (encrypts Client Secret)
// ============================================

export async function saveGoogleBusinessProfileConfig(data: {
  clientId: string;
  clientSecret: string;
  redirectUri: string;
  enabled?: boolean;
  updatedBy?: string;
}): Promise<{ success: boolean; error?: string }> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  try {
    const encrypted = encryptApiKey(data.clientSecret);

    await GoogleBusinessProfileConfig.findOneAndUpdate(
      { companyId: 'platform' },
      {
        clientId: data.clientId,
        encryptedClientSecret: encrypted.encrypted,
        clientSecretIV: encrypted.iv,
        redirectUri: data.redirectUri,
        enabled: data.enabled !== undefined ? data.enabled : true,
        status: 'disconnected', // Reset status until validated
        updatedBy: data.updatedBy,
        lastValidatedAt: null,
      },
      { upsert: true, new: true }
    );

    return { success: true };
  } catch (error: any) {
    console.error('[GoogleBusinessProfileConfigService] Failed to save config:', error);
    return { success: false, error: error.message || 'Failed to save configuration' };
  }
}

// ============================================
// DELETE CONFIG
// ============================================

export async function deleteGoogleBusinessProfileConfig(): Promise<{ success: boolean; error?: string }> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  try {
    await GoogleBusinessProfileConfig.deleteOne({ companyId: 'platform' });
    return { success: true };
  } catch (error: any) {
    console.error('[GoogleBusinessProfileConfigService] Failed to delete config:', error);
    return { success: false, error: error.message || 'Failed to delete configuration' };
  }
}

// ============================================
// GET CREDENTIALS (decrypted — for backend use only)
// ============================================

export async function getGoogleBusinessProfileCredentials(): Promise<{
  clientId: string;
  clientSecret: string;
  redirectUri: string;
} | null> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  try {
    const config = await GoogleBusinessProfileConfig.findOne({ companyId: 'platform' })
      .select('+encryptedClientSecret +clientSecretIV');

    if (!config || !config.enabled) {
      return null;
    }

    const clientSecret = decryptGBPSecret(config as any);
    if (!clientSecret) {
      console.error('[GoogleBusinessProfileConfigService] Failed to decrypt Client Secret');
      return null;
    }

    return {
      clientId: config.clientId,
      clientSecret,
      redirectUri: config.redirectUri,
    };
  } catch (error) {
    console.error('[GoogleBusinessProfileConfigService] Failed to get credentials:', error);
    return null;
  }
}

// ============================================
// TEST CONNECTION
// ============================================

export async function testGoogleBusinessProfileConnection(): Promise<{
  success: boolean;
  error?: string;
}> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  try {
    const credentials = await getGoogleBusinessProfileCredentials();
    if (!credentials) {
      return { success: false, error: 'Google Business Profile integration is not configured or is disabled' };
    }

    // Verify the credentials are non-empty
    if (!credentials.clientId || !credentials.clientSecret) {
      return { success: false, error: 'Client ID and Client Secret are required' };
    }

    // Validate credentials by attempting to construct a Google OAuth URL
    // and making a lightweight request to verify the Client ID is registered.
    // We use the token info endpoint — sending an invalid request that still
    // confirms the Client ID exists in Google's system.
    try {
      const validateUrl = `https://oauth2.googleapis.com/tokeninfo?client_id=${encodeURIComponent(credentials.clientId)}`;
      const response = await fetch(validateUrl, { method: 'GET', signal: AbortSignal.timeout(10000) });

      // A valid (registered) Client ID will return a JSON response (even if
      // the token parameter is missing — the response confirms the client_id
      // exists). An unregistered Client ID returns a 400 with "invalid client".
      if (response.status === 400) {
        const body: any = await response.json().catch(() => ({}));
        if (body.error === 'invalid_client' || body.error_description?.includes('Invalid client')) {
          await GoogleBusinessProfileConfig.findOneAndUpdate(
            { companyId: 'platform' },
            { status: 'error' }
          ).catch(() => {});
          return { success: false, error: 'Invalid Client ID — the Client ID is not registered in Google Cloud Console' };
        }
      }
    } catch (fetchError: any) {
      // Network errors (timeout, DNS failure) are non-fatal for this check.
      // The credentials might still be valid — we just can't verify right now.
      console.warn('[GoogleBusinessProfileConfigService] Could not verify Client ID with Google:', fetchError.message);
    }

    // Update status to connected
    await GoogleBusinessProfileConfig.findOneAndUpdate(
      { companyId: 'platform' },
      { status: 'connected', lastValidatedAt: new Date() }
    );

    return { success: true };
  } catch (error: any) {
    // Update status to error
    await GoogleBusinessProfileConfig.findOneAndUpdate(
      { companyId: 'platform' },
      { status: 'error' }
    ).catch(() => {});

    return { success: false, error: error.message || 'Failed to test connection' };
  }
}

// ============================================
// TOGGLE ENABLED
// ============================================

export async function toggleGoogleBusinessProfileEnabled(enabled: boolean): Promise<{
  success: boolean;
  enabled: boolean;
  error?: string;
}> {
  const { getModels } = await import('../../models');
  const { GoogleBusinessProfileConfig } = getModels();

  try {
    const config = await GoogleBusinessProfileConfig.findOne({ companyId: 'platform' });
    if (!config) {
      return { success: false, enabled: false, error: 'Configuration not found. Please save credentials first.' };
    }

    config.enabled = enabled;
    await config.save();

    return { success: true, enabled: config.enabled };
  } catch (error: any) {
    return { success: false, enabled: false, error: error.message || 'Failed to toggle integration' };
  }
}