/**
 * Gemini Orchestrator State Machine
 * 
 * Manages chat flow states and proactive triggers for the orchestrated conversation.
 * Gemini acts as the intelligence that decides when and how to engage.
 */

import { t } from '@/lib/i18n';

// ============================================================================
// Types & Interfaces
// ============================================================================

export type OrchestratorState = 
  | 'IDLE'              // Waiting for user input
  | 'USER_TYPING'       // User is actively typing
  | 'PROCESSING'        // Gemini is analyzing
  | 'STREAMING_QUICK'   // GPT is streaming quick response
  | 'STREAMING_DETAIL'  // GPT is streaming detailed follow-up
  | 'COOLDOWN'          // Brief pause after response
  | 'PROACTIVE_READY';  // Ready to send proactive message

export type OrchestratorAction =
  | 'RESPOND'
  | 'RESPOND_WITH_WIDGET'
  | 'ASK_FOLLOWUP'
  | 'WAIT_FOR_USER'
  | 'PROACTIVE_ENGAGE';

export interface OrchestratorContext {
  conversationId: string | null;
  lastMessageTimestamp: number;
  lastBotResponseTimestamp: number;
  userTypingStarted: number | null;
  userTypingStopped: number | null;
  consecutiveBotMessages: number;
  shownWidgets: string[];
  idleSeconds: number;
  totalMessages: number;
}

export interface ProactiveTriggerConfig {
  enabled: boolean;
  minIdleSeconds: number;           // Min seconds before proactive trigger
  maxIdleSeconds: number;           // Max seconds to wait
  typingPauseThreshold: number;     // Seconds of pause after typing stops
  maxConsecutiveBotMessages: number; // Don't spam user
  cooldownAfterResponse: number;    // Seconds to wait after bot response
}

// ============================================================================
// Logger
// ============================================================================

const LOG_PREFIX = '[BoostBot][Orchestrator]';

function log(level: 'debug' | 'info' | 'warn' | 'error', message: string, data?: unknown) {
  const timestamp = new Date().toISOString();
  const formatted = `${LOG_PREFIX}[${level.toUpperCase()}] ${message}`;
  
  if (data !== undefined) {
    console[level](formatted, data);
  } else {
    console[level](formatted);
  }
  
  // Store in session for debugging
  try {
    const logs = JSON.parse(sessionStorage.getItem('boostbot_orchestrator_logs') || '[]');
    logs.push({ timestamp, level, message, data: data ? JSON.stringify(data) : null });
    // Keep last 100 logs
    if (logs.length > 100) logs.shift();
    sessionStorage.setItem('boostbot_orchestrator_logs', JSON.stringify(logs));
  } catch {
    // Ignore storage errors
  }
}

// ============================================================================
// Orchestrator State Machine
// ============================================================================

class OrchestratorStateMachine {
  private state: OrchestratorState = 'IDLE';
  private context: OrchestratorContext;
  private config: ProactiveTriggerConfig;
  
  // Timers
  private idleTimer: ReturnType<typeof setInterval> | null = null;
  private proactiveTimer: ReturnType<typeof setTimeout> | null = null;
  private typingDebounce: ReturnType<typeof setTimeout> | null = null;
  
  // Callbacks
  private onProactiveMessage: ((message: string, widget?: { type: string }) => void) | null = null;
  private onStateChange: ((state: OrchestratorState) => void) | null = null;
  private onThinking: ((message: string | null) => void) | null = null;
  
  // Session token for API calls
  private sessionToken: string | null = null;
  private streamUrl: string | null = null;

  constructor() {
    this.context = this.createInitialContext();
    this.config = this.getDefaultConfig();
    
    log('info', 'Orchestrator initialized', { state: this.state });
  }

  private createInitialContext(): OrchestratorContext {
    return {
      conversationId: null,
      lastMessageTimestamp: 0,
      lastBotResponseTimestamp: 0,
      userTypingStarted: null,
      userTypingStopped: null,
      consecutiveBotMessages: 0,
      shownWidgets: [],
      idleSeconds: 0,
      totalMessages: 0,
    };
  }

  private getDefaultConfig(): ProactiveTriggerConfig {
    return {
      enabled: true,
      minIdleSeconds: 8,              // Wait at least 8 seconds
      maxIdleSeconds: 30,             // Max 30 seconds
      typingPauseThreshold: 3,        // 3 seconds after typing stops
      maxConsecutiveBotMessages: 2,   // Max 2 consecutive bot messages
      cooldownAfterResponse: 5,       // 5 seconds cooldown
    };
  }

  // ============================================================================
  // Public API
  // ============================================================================

  /**
   * Initialize with session credentials
   */
  setSession(token: string, streamUrl: string) {
    this.sessionToken = token;
    this.streamUrl = streamUrl;
    log('debug', 'Session set', { hasToken: !!token, streamUrl });
  }

  /**
   * Set conversation ID
   */
  setConversationId(id: string) {
    this.context.conversationId = id;
    log('debug', 'Conversation ID set', { id });
  }

  /**
   * Register callbacks
   */
  onProactive(callback: (message: string, widget?: { type: string }) => void) {
    this.onProactiveMessage = callback;
  }

  onState(callback: (state: OrchestratorState) => void) {
    this.onStateChange = callback;
  }

  onThinkingChange(callback: (message: string | null) => void) {
    this.onThinking = callback;
  }

  /**
   * Configure proactive triggers
   */
  configure(config: Partial<ProactiveTriggerConfig>) {
    this.config = { ...this.config, ...config };
    log('debug', 'Config updated', this.config);
  }

  /**
   * User started typing
   */
  userStartedTyping() {
    if (this.state === 'USER_TYPING') return;
    
    log('debug', 'User started typing');
    this.context.userTypingStarted = Date.now();
    this.context.userTypingStopped = null;
    this.transition('USER_TYPING');
    
    // Cancel any pending proactive triggers
    this.cancelProactiveTrigger();
  }

  /**
   * User stopped typing (debounced)
   */
  userStoppedTyping() {
    // Debounce to avoid flickering
    if (this.typingDebounce) {
      clearTimeout(this.typingDebounce);
    }
    
    this.typingDebounce = setTimeout(() => {
      log('debug', 'User stopped typing');
      this.context.userTypingStopped = Date.now();
      
      // If we're still waiting for user input
      if (this.state === 'USER_TYPING') {
        this.transition('IDLE');
        this.startIdleTimer();
        
        // Check if we should trigger proactive after typing pause
        this.scheduleTypingPauseTrigger();
      }
    }, 500); // 500ms debounce
  }

  /**
   * User sent a message
   */
  userSentMessage() {
    log('debug', 'User sent message');
    this.context.lastMessageTimestamp = Date.now();
    this.context.totalMessages++;
    this.context.consecutiveBotMessages = 0;
    this.context.idleSeconds = 0;
    
    this.cancelProactiveTrigger();
    this.stopIdleTimer();
    this.transition('PROCESSING');
  }

  /**
   * Bot started streaming (quick response)
   */
  botStartedStreaming(phase: 'quick' | 'detailed') {
    log('debug', `Bot started streaming (${phase})`);
    this.transition(phase === 'quick' ? 'STREAMING_QUICK' : 'STREAMING_DETAIL');
  }

  /**
   * Bot finished streaming
   */
  botFinishedStreaming(hasFollowup: boolean) {
    log('debug', 'Bot finished streaming', { hasFollowup });
    this.context.lastBotResponseTimestamp = Date.now();
    this.context.consecutiveBotMessages++;
    
    if (hasFollowup) {
      // Gemini is analyzing for follow-up
      this.transition('PROCESSING');
      if (this.onThinking) {
        this.onThinking('🔍 ...');
      }
    } else {
      // Start cooldown, then enable proactive triggers
      this.transition('COOLDOWN');
      this.startCooldown();
    }
  }

  /**
   * Widget was shown
   */
  widgetShown(widgetType: string) {
    if (!this.context.shownWidgets.includes(widgetType)) {
      this.context.shownWidgets.push(widgetType);
      log('debug', 'Widget shown', { widgetType, all: this.context.shownWidgets });
    }
  }

  /**
   * Get current state
   */
  getState(): OrchestratorState {
    return this.state;
  }

  /**
   * Get context for debugging
   */
  getContext(): OrchestratorContext {
    return { ...this.context };
  }

  /**
   * Check if widget has been shown
   */
  hasShownWidget(widgetType: string): boolean {
    return this.context.shownWidgets.includes(widgetType);
  }

  /**
   * Reset state (e.g., on new conversation)
   */
  reset() {
    log('info', 'Orchestrator reset');
    this.cancelProactiveTrigger();
    this.stopIdleTimer();
    this.context = this.createInitialContext();
    this.transition('IDLE');
  }

  /**
   * Cleanup
   */
  destroy() {
    log('info', 'Orchestrator destroyed');
    this.cancelProactiveTrigger();
    this.stopIdleTimer();
    if (this.typingDebounce) {
      clearTimeout(this.typingDebounce);
    }
  }

  // ============================================================================
  // Private Methods
  // ============================================================================

  private transition(newState: OrchestratorState) {
    const oldState = this.state;
    this.state = newState;
    
    log('info', `State transition: ${oldState} → ${newState}`);
    
    if (this.onStateChange) {
      this.onStateChange(newState);
    }
  }

  private startIdleTimer() {
    this.stopIdleTimer();
    
    this.idleTimer = setInterval(() => {
      this.context.idleSeconds++;
      
      // Check if we should trigger proactive message
      if (this.shouldTriggerProactive()) {
        this.triggerProactive();
      }
    }, 1000);
    
    log('debug', 'Idle timer started');
  }

  private stopIdleTimer() {
    if (this.idleTimer) {
      clearInterval(this.idleTimer);
      this.idleTimer = null;
      log('debug', 'Idle timer stopped');
    }
  }

  private startCooldown() {
    const cooldownMs = this.config.cooldownAfterResponse * 1000;
    
    log('debug', `Starting cooldown (${this.config.cooldownAfterResponse}s)`);
    
    setTimeout(() => {
      if (this.state === 'COOLDOWN') {
        this.transition('PROACTIVE_READY');
        this.startIdleTimer();
      }
    }, cooldownMs);
  }

  private scheduleTypingPauseTrigger() {
    if (!this.config.enabled) return;
    if (this.context.consecutiveBotMessages >= this.config.maxConsecutiveBotMessages) return;
    
    const delay = this.config.typingPauseThreshold * 1000;
    
    log('debug', `Scheduling typing pause trigger (${this.config.typingPauseThreshold}s)`);
    
    this.proactiveTimer = setTimeout(() => {
      // User started typing but stopped - might need help
      if (this.state === 'IDLE' && this.context.userTypingStopped) {
        const pauseDuration = (Date.now() - this.context.userTypingStopped) / 1000;
        
        if (pauseDuration >= this.config.typingPauseThreshold) {
          log('info', 'Typing pause trigger fired', { pauseDuration });
          this.triggerProactive('typing_pause');
        }
      }
    }, delay);
  }

  private cancelProactiveTrigger() {
    if (this.proactiveTimer) {
      clearTimeout(this.proactiveTimer);
      this.proactiveTimer = null;
      log('debug', 'Proactive trigger cancelled');
    }
  }

  private shouldTriggerProactive(): boolean {
    if (!this.config.enabled) return false;
    if (this.state !== 'PROACTIVE_READY' && this.state !== 'IDLE') return false;
    if (this.context.idleSeconds < this.config.minIdleSeconds) return false;
    if (this.context.consecutiveBotMessages >= this.config.maxConsecutiveBotMessages) return false;
    if (this.context.totalMessages < 1) return false; // Need at least one exchange
    
    return true;
  }

  private async triggerProactive(reason: string = 'idle') {
    if (!this.sessionToken || !this.streamUrl) {
      log('warn', 'Cannot trigger proactive - no session');
      return;
    }

    log('info', 'Triggering proactive message', { 
      reason, 
      idleSeconds: this.context.idleSeconds,
      consecutiveBotMessages: this.context.consecutiveBotMessages 
    });

    this.cancelProactiveTrigger();
    this.stopIdleTimer();
    this.transition('PROCESSING');

    try {
      // Call orchestrator with proactive context
      const orchestrateUrl = this.streamUrl.replace('/chat/stream', '/chat/orchestrate');
      
      const response = await fetch(orchestrateUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${this.sessionToken}`,
        },
        body: JSON.stringify({
          message: '[PROACTIVE_TRIGGER]',
          history: [],
          small_chunks: '',
          large_chunks: '',
          page_content: '',
          bot_config: {
            name: 'BoostBot',
            output_limit: 400,
            enabled_widgets: ['lead_form'],
            language: 'he',
          },
          shown_widgets: this.context.shownWidgets,
          phase: 'proactive',
          proactive_context: {
            reason,
            idle_seconds: this.context.idleSeconds,
            consecutive_bot_messages: this.context.consecutiveBotMessages,
            total_messages: this.context.totalMessages,
          },
          conversation_id: this.context.conversationId,
        }),
      });

      const data = await response.json();
      
      if (data.success && data.data) {
        const { action, widget } = data.data;
        
        log('info', 'Proactive orchestration result', { action, hasWidget: !!widget });
        
        if (action !== 'WAIT_FOR_USER' && this.onProactiveMessage) {
          // Use a simple proactive message
          const proactiveMessages = [
            t('Do you have more questions? Happy to help') + ' 😊',
            t('Would you like me to connect you with a representative?'),
            t('Was this information helpful?'),
          ];
          const randomMessage = proactiveMessages[Math.floor(Math.random() * proactiveMessages.length)];
          
          this.onProactiveMessage(randomMessage, widget);
          this.context.consecutiveBotMessages++;
          this.context.lastBotResponseTimestamp = Date.now();
        }
      }
      
      this.transition('COOLDOWN');
      this.startCooldown();
      
    } catch (error) {
      log('error', 'Proactive trigger failed', error);
      this.transition('IDLE');
      this.startIdleTimer();
    }
  }
}

// ============================================================================
// Singleton Export
// ============================================================================

export const orchestrator = new OrchestratorStateMachine();

// Export logging utility for external use
export function getOrchestratorLogs(): Array<{ timestamp: string; level: string; message: string; data: string | null }> {
  try {
    return JSON.parse(sessionStorage.getItem('boostbot_orchestrator_logs') || '[]');
  } catch {
    return [];
  }
}

export function clearOrchestratorLogs() {
  sessionStorage.removeItem('boostbot_orchestrator_logs');
}
