/**
 * TextMe Clawdbot Channel Plugin
 * 
 * External channel plugin for integrating TextMe messaging with Clawdbot.
 * 
 * Features:
 * - Multi-account support (multiple TextMe phone numbers)
 * - Persistent authentication with auto-refresh
 * - Inbound messages via WebSocket
 * - Outbound messages via REST API
 * - Standard Clawdbot channel plugin interface
 */

import {
  ConfigManager,
  getConfigManager,
  type PluginConfig,
  type AccountConfig,
} from './config.js';
import { AuthManager, createAuthManager, type AuthenticatedAccount } from './auth.js';
import { InboundHandler, createInboundHandler, type ClawdbotMessage } from './inbound.js';
import {
  OutboundHandler,
  createOutboundHandler,
  type OutboundRequest,
  type OutboundResponse,
  type ProbeResponse,
} from './outbound.js';

// ============================================================================
// Re-exports
// ============================================================================

export type {
  PluginConfig,
  AccountConfig,
  AuthenticatedAccount,
  ClawdbotMessage,
  OutboundRequest,
  OutboundResponse,
  ProbeResponse,
};

export {
  ConfigManager,
  getConfigManager,
  AuthManager,
  createAuthManager,
  InboundHandler,
  createInboundHandler,
  OutboundHandler,
  createOutboundHandler,
};

// ============================================================================
// Plugin Class
// ============================================================================

export interface TextMeChannelPluginOptions {
  /** Path to configuration file */
  configPath?: string;
  /** Enable debug logging */
  debug?: boolean;
  /** Custom message handler (bypasses gateway forwarding) */
  onMessage?: (message: ClawdbotMessage, account: AuthenticatedAccount) => Promise<void>;
}

export interface PluginStatus {
  running: boolean;
  accounts: {
    id: string;
    name: string;
    authenticated: boolean;
    connected: boolean;
    phoneNumbers: string[];
  }[];
  webhookUrl: string;
}

export class TextMeChannelPlugin {
  private configManager: ConfigManager;
  private authManager: AuthManager | null = null;
  private inboundHandler: InboundHandler | null = null;
  private outboundHandler: OutboundHandler | null = null;
  private config: PluginConfig | null = null;
  private isRunning = false;
  private options: TextMeChannelPluginOptions;

  constructor(options: TextMeChannelPluginOptions = {}) {
    this.options = options;
    this.configManager = getConfigManager(options.configPath);
  }

  /**
   * Initialize and start the plugin
   */
  async start(): Promise<void> {
    if (this.isRunning) {
      console.log('[TextMePlugin] Already running');
      return;
    }

    console.log('[TextMePlugin] Starting...');

    // Load configuration
    this.config = await this.configManager.load();
    
    if (this.options.debug !== undefined) {
      this.config.debug = this.options.debug;
    }

    this.log('Configuration loaded');
    this.log(`  Accounts: ${this.config.accounts.length}`);
    this.log(`  Gateway URL: ${this.config.clawdbotGatewayUrl}`);
    this.log(`  Webhook Port: ${this.config.webhookPort}`);

    // Initialize authentication
    this.authManager = createAuthManager(this.configManager, {
      debug: this.config.debug,
    });

    const authenticatedAccounts = await this.authManager.initialize();
    this.log(`Authenticated ${authenticatedAccounts.length} accounts`);

    // Initialize inbound handler
    this.inboundHandler = new InboundHandler(this.authManager, {
      gatewayUrl: this.config.clawdbotGatewayUrl,
      gatewayToken: this.config.clawdbotGatewayToken,
      debug: this.config.debug,
      onMessage: this.options.onMessage,
      realtimeOptions: {
        autoReconnect: this.config.autoReconnect,
        maxReconnectAttempts: this.config.maxReconnectAttempts,
        reconnectDelay: this.config.reconnectDelay,
      },
    });

    await this.inboundHandler.start();
    this.log('Inbound handler started');

    // Initialize outbound handler
    this.outboundHandler = createOutboundHandler(this.authManager, this.config);
    await this.outboundHandler.start();
    this.log(`Outbound handler started at ${this.outboundHandler.getAddress()}`);

    this.isRunning = true;
    console.log('[TextMePlugin] Started successfully');
  }

  /**
   * Stop the plugin
   */
  async stop(): Promise<void> {
    if (!this.isRunning) {
      return;
    }

    console.log('[TextMePlugin] Stopping...');

    // Stop handlers
    if (this.inboundHandler) {
      await this.inboundHandler.stop();
      this.inboundHandler = null;
    }

    if (this.outboundHandler) {
      await this.outboundHandler.stop();
      this.outboundHandler = null;
    }

    // Shutdown auth
    if (this.authManager) {
      await this.authManager.shutdown();
      this.authManager = null;
    }

    this.isRunning = false;
    console.log('[TextMePlugin] Stopped');
  }

  /**
   * Get plugin status
   */
  getStatus(): PluginStatus {
    const accounts = this.authManager?.getAllAccounts() || [];
    const connectionStatus = this.inboundHandler?.getConnectionStatus() || new Map();

    return {
      running: this.isRunning,
      accounts: accounts.map(acc => ({
        id: acc.account.id,
        name: acc.account.name,
        authenticated: true,
        connected: connectionStatus.get(acc.account.id) || false,
        phoneNumbers: acc.account.phoneNumbers,
      })),
      webhookUrl: this.outboundHandler?.getAddress() || '',
    };
  }

  /**
   * Send a message (programmatic access)
   */
  async send(request: OutboundRequest): Promise<OutboundResponse> {
    if (!this.outboundHandler) {
      return {
        success: false,
        error: 'Plugin not running',
      };
    }
    return this.outboundHandler.sendMessage(request);
  }

  /**
   * Probe endpoint (channel plugin interface)
   */
  async probe(): Promise<ProbeResponse> {
    const accounts = this.config?.accounts || [];
    const authenticatedAccounts = this.authManager?.getAllAccounts() || [];

    return {
      channel: 'textme',
      version: '1.0.0',
      capabilities: ['send', 'receive', 'attachments', 'multi-account'],
      accounts: accounts.map(acc => ({
        id: acc.id,
        name: acc.name,
        phoneNumbers: acc.phoneNumbers,
        enabled: acc.enabled,
      })),
      status: authenticatedAccounts.length > 0 ? 'ready' : 'offline',
    };
  }

  /**
   * Get authenticated account by ID
   */
  getAccount(accountId: string): AuthenticatedAccount | undefined {
    return this.authManager?.getAccount(accountId);
  }

  /**
   * Get all authenticated accounts
   */
  getAccounts(): AuthenticatedAccount[] {
    return this.authManager?.getAllAccounts() || [];
  }

  /**
   * Reconnect a specific account
   */
  async reconnectAccount(accountId: string): Promise<void> {
    if (this.inboundHandler) {
      await this.inboundHandler.reconnectAccount(accountId);
    }
  }

  /**
   * Debug logging
   */
  private log(message: string): void {
    if (this.config?.debug || this.options.debug) {
      console.log(`[TextMePlugin] ${message}`);
    }
  }
}

// ============================================================================
// Factory Functions
// ============================================================================

/**
 * Create a new TextMe channel plugin instance
 */
export function createTextMeChannelPlugin(
  options?: TextMeChannelPluginOptions
): TextMeChannelPlugin {
  return new TextMeChannelPlugin(options);
}

// ============================================================================
// CLI Entry Point
// ============================================================================

async function main(): Promise<void> {
  const plugin = createTextMeChannelPlugin({
    debug: process.env.TEXTME_DEBUG === 'true',
  });

  // Handle shutdown signals
  const shutdown = async (signal: string) => {
    console.log(`\n[TextMePlugin] Received ${signal}, shutting down...`);
    await plugin.stop();
    process.exit(0);
  };

  process.on('SIGINT', () => shutdown('SIGINT'));
  process.on('SIGTERM', () => shutdown('SIGTERM'));

  try {
    await plugin.start();
    
    const status = plugin.getStatus();
    console.log('\n[TextMePlugin] Ready!');
    console.log(`  Webhook URL: ${status.webhookUrl}`);
    console.log(`  Accounts: ${status.accounts.length}`);
    status.accounts.forEach(acc => {
      console.log(`    - ${acc.name} (${acc.id}): ${acc.connected ? 'connected' : 'disconnected'}`);
      console.log(`      Phone numbers: ${acc.phoneNumbers.join(', ')}`);
    });
    console.log('\nPress Ctrl+C to stop.\n');
  } catch (err) {
    console.error('[TextMePlugin] Failed to start:', err);
    process.exit(1);
  }
}

// Run if executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
  main().catch(console.error);
}

// ============================================================================
// Default Export
// ============================================================================

export default TextMeChannelPlugin;
