/**
 * Facebook N8n Configuration Model
 *
 * Stores per-company Facebook publishing configuration for the n8n integration.
 * Unlike the direct Facebook integration (which uses OAuth), this channel
 * relies on the user manually configuring credentials. n8n acts as the
 * publishing middleware:
 *
 *   Mengo → n8n webhook → n8n publishes to Facebook → n8n calls back → Mengo updates status
 *
 * Two publishing methods are supported:
 *
 *   1. Facebook Graph API (Recommended) — Uses App ID, App Secret, Page ID,
 *      and Page Access Token. The n8n workflow calls the Facebook Graph API
 *      directly to publish posts.
 *
 *   2. Browser Automation (Experimental) — Uses Facebook Login Email, Login
 *      Password, and Target Page/Profile. The n8n workflow uses Playwright or
 *      Selenium to automate posting via the Facebook website.
 *
 * Security:
 * - All secrets (Page Access Token, App Secret, Login Email, Login Password)
 *   are AES-256-GCM encrypted at rest using the same encryption module.
 * - Webhook URL, Page ID, and Target Page Profile are plain text (not secrets).
 * - Callback URL is auto-generated and includes a verification token.
 * - The encrypted fields use `select: false` so they are excluded from
 *   default Mongoose queries.
 */

import mongoose, { Schema, Document } from 'mongoose';
import { encryptApiKey, decryptApiKey } from '../services/utils/encryption';

// ============================================
// TYPE DEFINITIONS
// ============================================

export type FacebookN8nConfigStatus = 'connected' | 'disconnected';
export type FacebookN8nPublishMethod = 'graph_api' | 'browser_automation';

export interface IFacebookN8nConfig extends Document {
  companyId: string;
  /** Publishing method: graph_api uses Facebook Graph API credentials,
   *  browser_automation uses Facebook login credentials for browser automation */
  publishMethod: FacebookN8nPublishMethod;
  /** n8n webhook URL that Mengo sends payloads to (plain text — not a secret) */
  webhookUrl: string;

  // ── Graph API method fields ──
  /** Facebook Page ID for Graph API method (plain text — not a secret) */
  pageId?: string;
  /** Encrypted Facebook Page Access Token — stored as "ciphertext:authTag" */
  encryptedPageAccessToken?: string;
  /** IV for the encrypted Page Access Token */
  pageAccessTokenIV?: string;
  /** Encrypted Facebook App ID — stored as "ciphertext:authTag" */
  encryptedAppId?: string;
  /** IV for the encrypted App ID */
  appIdIV?: string;
  /** Encrypted Facebook App Secret — stored as "ciphertext:authTag" */
  encryptedAppSecret?: string;
  /** IV for the encrypted App Secret */
  appSecretIV?: string;

  // ── Browser Automation method fields ──
  /** Encrypted Facebook Login Email — stored as "ciphertext:authTag" */
  encryptedFbLoginEmail?: string;
  /** IV for the encrypted Login Email */
  fbLoginEmailIV?: string;
  /** Encrypted Facebook Login Password — stored as "ciphertext:authTag" */
  encryptedFbLoginPassword?: string;
  /** IV for the encrypted Login Password */
  fbLoginPasswordIV?: string;
  /** Target Facebook Page/Profile name or URL (plain text — not a secret) */
  targetPageProfile?: string;

  // ── Common fields ──
  /** Default post type for this channel */
  postType: 'text' | 'photo';
  /** Auto-generated callback URL that n8n calls back to (plain text) */
  callbackUrl?: string;
  /** Encrypted webhook verification token for callback authentication */
  encryptedCallbackToken?: string;
  callbackTokenIV?: string;
  /** Connection status */
  status: FacebookN8nConfigStatus;
  /** Who created/updated the config */
  createdBy?: string;
  updatedBy?: string;
  createdAt: Date;
  updatedAt: Date;
}

// ============================================
// HELPER: Decrypt functions
// ============================================

/**
 * Decrypt the Facebook Page Access Token from a config document.
 */
export function decryptPageAccessToken(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedPageAccessToken || !config.pageAccessTokenIV) return null;
  try {
    return decryptApiKey(config.encryptedPageAccessToken, config.pageAccessTokenIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt Page Access Token:', error);
    return null;
  }
}

/**
 * Decrypt the Facebook App ID from a config document.
 */
export function decryptAppId(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedAppId || !config.appIdIV) return null;
  try {
    return decryptApiKey(config.encryptedAppId, config.appIdIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt App ID:', error);
    return null;
  }
}

/**
 * Decrypt the Facebook App Secret from a config document.
 */
export function decryptAppSecret(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedAppSecret || !config.appSecretIV) return null;
  try {
    return decryptApiKey(config.encryptedAppSecret, config.appSecretIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt App Secret:', error);
    return null;
  }
}

/**
 * Decrypt the Facebook Login Email from a config document.
 */
export function decryptFbLoginEmail(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedFbLoginEmail || !config.fbLoginEmailIV) return null;
  try {
    return decryptApiKey(config.encryptedFbLoginEmail, config.fbLoginEmailIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt Login Email:', error);
    return null;
  }
}

/**
 * Decrypt the Facebook Login Password from a config document.
 */
export function decryptFbLoginPassword(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedFbLoginPassword || !config.fbLoginPasswordIV) return null;
  try {
    return decryptApiKey(config.encryptedFbLoginPassword, config.fbLoginPasswordIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt Login Password:', error);
    return null;
  }
}

/**
 * Decrypt the callback verification token from a config document.
 */
export function decryptCallbackToken(config: IFacebookN8nConfig): string | null {
  if (!config.encryptedCallbackToken || !config.callbackTokenIV) return null;
  try {
    return decryptApiKey(config.encryptedCallbackToken, config.callbackTokenIV);
  } catch (error) {
    console.error('[FacebookN8nConfig] Failed to decrypt callback token:', error);
    return null;
  }
}

/**
 * Mask a sensitive string for frontend display.
 * Shows first 4 chars, asterisks, last 4 chars.
 */
export function maskSecret(secret: string): string {
  if (!secret || secret.length <= 8) return '********';
  return secret.slice(0, 4) + '*'.repeat(secret.length - 8) + secret.slice(-4);
}

// ============================================
// MAIN SCHEMA
// ============================================

const FacebookN8nConfigSchema = new Schema<IFacebookN8nConfig>({
  companyId: {
    type: String,
    required: [true, 'Company ID is required'],
    unique: true,
  },
  publishMethod: {
    type: String,
    enum: ['graph_api', 'browser_automation'],
    default: 'graph_api',
  },
  webhookUrl: {
    type: String,
    required: [true, 'Webhook URL is required'],
    trim: true,
  },
  // ── Graph API method fields ──
  pageId: {
    type: String,
    trim: true,
  },
  encryptedPageAccessToken: {
    type: String,
    select: false,
  },
  pageAccessTokenIV: {
    type: String,
    select: false,
  },
  encryptedAppId: {
    type: String,
    select: false,
  },
  appIdIV: {
    type: String,
    select: false,
  },
  encryptedAppSecret: {
    type: String,
    select: false,
  },
  appSecretIV: {
    type: String,
    select: false,
  },
  // ── Browser Automation method fields ──
  encryptedFbLoginEmail: {
    type: String,
    select: false,
  },
  fbLoginEmailIV: {
    type: String,
    select: false,
  },
  encryptedFbLoginPassword: {
    type: String,
    select: false,
  },
  fbLoginPasswordIV: {
    type: String,
    select: false,
  },
  targetPageProfile: {
    type: String,
    trim: true,
  },
  // ── Common fields ──
  postType: {
    type: String,
    enum: ['text', 'photo'],
    default: 'text',
  },
  callbackUrl: {
    type: String,
  },
  encryptedCallbackToken: {
    type: String,
    select: false,
  },
  callbackTokenIV: {
    type: String,
    select: false,
  },
  status: {
    type: String,
    enum: ['connected', 'disconnected'],
    default: 'disconnected',
  },
  createdBy: {
    type: String,
  },
  updatedBy: {
    type: String,
  },
}, {
  timestamps: true,
});

// ============================================
// INDEXES
// ============================================

FacebookN8nConfigSchema.index({ companyId: 1 }, { unique: true });

// ============================================
// EXPORT
// ============================================

export const FacebookN8nConfig = mongoose.models.FacebookN8nConfig || mongoose.model<IFacebookN8nConfig>('FacebookN8nConfig', FacebookN8nConfigSchema);