/**
 * PWA Keyboard Tracker
 * 
 * Advanced keyboard tracking for PWA environments
 * Extracted from Holy Habit holy-editor-pro.js
 */

import { PWAEnvironment, KeyboardTrackingSettings, PlatformInfo, KeyboardOffsetData } from '../types/Editor';

export class PWAKeyboardTracker {
  private toolbar: HTMLElement | null = null;
  private editorRoot: HTMLElement | null = null;
  private settings: KeyboardTrackingSettings;
  private lastKeyboardHeight = 0;
  private updateTimeout: NodeJS.Timeout | null = null;
  private isActive = false;

  constructor(settings?: Partial<KeyboardTrackingSettings>) {
    this.settings = {
      threshold: 10,
      keyboardMin: 150,
      debounceTime: 0,
      ...settings
    };
  }

  /**
   * Initialize keyboard tracking
   */
  public initialize(editorRoot: HTMLElement, toolbarSelector: string = '.vertical-toolbar, .mobile-toolbar, .toolbar'): void {
    this.editorRoot = editorRoot;
    this.toolbar = document.querySelector(toolbarSelector);
    
    if (!this.toolbar) {
      console.warn('⚠️ Toolbar element not found for keyboard tracking');
      return;
    }

    console.log('📱 PWA keyboard tracking initialization');
    
    // Log environment information
    const env = this.getEnvironmentInfo();
    console.log('📱 Environment info:', env);
    
    // Setup tracking based on Visual Viewport API support
    if (this.hasVisualViewport()) {
      this.setupEnhancedKeyboardTracking();
    } else {
      this.setupFallbackKeyboardTracking();
    }

    this.isActive = true;
  }

  /**
   * Destroy keyboard tracking
   */
  public destroy(): void {
    this.isActive = false;
    
    if (this.updateTimeout) {
      clearTimeout(this.updateTimeout);
      this.updateTimeout = null;
    }

    // Remove event listeners
    const events = ['resize', 'orientationchange', 'scroll'];
    events.forEach(evt => window.removeEventListener(evt, this.debouncedUpdate));

    if (this.hasVisualViewport()) {
      window.visualViewport?.removeEventListener('resize', this.debouncedUpdate);
      window.visualViewport?.removeEventListener('scroll', this.debouncedUpdate);
    }

    // Reset toolbar position
    if (this.toolbar) {
      this.toolbar.style.transform = 'translateY(0)';
      this.toolbar.style.webkitTransform = 'translateY(0)';
      this.toolbar.classList.remove('keyboard-tracking');
    }

    document.body.classList.remove('keyboard-active');
    
    console.log('📱 PWA keyboard tracking destroyed');
  }

  /**
   * Get current environment information
   */
  public getEnvironmentInfo(): PWAEnvironment {
    return {
      isPWA: this.isPWA(),
      isIOS: this.isIOS(),
      isAndroid: this.isAndroid(),
      hasVisualViewport: this.hasVisualViewport(),
      isAndroidChrome: this.isAndroidChrome(),
      isSamsungInternet: this.isSamsungInternet()
    };
  }

  /**
   * Update keyboard tracking settings
   */
  public updateSettings(newSettings: Partial<KeyboardTrackingSettings>): void {
    this.settings = { ...this.settings, ...newSettings };
    console.log('📱 Keyboard tracking settings updated:', this.settings);
  }

  // Platform detection methods
  public isPWA(): boolean {
    return window.matchMedia('(display-mode: standalone)').matches ||
           (window.navigator as any).standalone === true ||
           document.referrer.includes('android-app://');
  }

  public isIOS(): boolean {
    return /iP(hone|od|ad)/.test(navigator.userAgent) && !(window as any).MSStream;
  }

  public isAndroid(): boolean {
    return /Android/.test(navigator.userAgent);
  }

  public isAndroidChrome(): boolean {
    return /Android/.test(navigator.userAgent) && /Chrome/.test(navigator.userAgent);
  }

  public isSamsungInternet(): boolean {
    return /SamsungBrowser/.test(navigator.userAgent);
  }

  public hasVisualViewport(): boolean {
    return 'visualViewport' in window;
  }

  // Enhanced keyboard tracking (Visual Viewport API)
  private setupEnhancedKeyboardTracking(): void {
    console.log('📱 Enhanced keyboard tracking enabled (Visual Viewport API)');
    
    // Event listener registration
    const events = ['resize', 'orientationchange', 'scroll'];
    events.forEach(evt => window.addEventListener(evt, this.debouncedUpdate));
    
    // Visual Viewport events
    if (window.visualViewport) {
      window.visualViewport.addEventListener('resize', this.debouncedUpdate);
      window.visualViewport.addEventListener('scroll', this.debouncedUpdate);
    }
    
    // Focus events
    document.body.addEventListener('focusin', this.debouncedUpdate);
    document.body.addEventListener('focusout', this.handleFocusOut);
    
    // Initial position setup
    setTimeout(() => this.updateToolbarPosition(), 100);
  }

  // Fallback keyboard tracking
  private setupFallbackKeyboardTracking(): void {
    console.log('📱 Fallback keyboard tracking enabled (height estimation)');
    
    let isKeyboardVisible = false;
    let initialHeight = window.innerHeight;
    
    const showKeyboard = () => {
      if (!isKeyboardVisible && this.toolbar) {
        isKeyboardVisible = true;
        document.body.classList.add('keyboard-active');
        this.toolbar.classList.add('keyboard-up');
        
        // Estimated keyboard height
        const estimatedHeight = this.isIOS() ? 260 : 300;
        this.applyToolbarTransform(this.toolbar, estimatedHeight);
        
        console.log('📱 Keyboard shown (estimated):', estimatedHeight);
      }
    };
    
    const hideKeyboard = () => {
      if (isKeyboardVisible && this.toolbar) {
        isKeyboardVisible = false;
        document.body.classList.remove('keyboard-active');
        this.toolbar.classList.remove('keyboard-up');
        this.toolbar.style.transform = 'translateY(0)';
        this.toolbar.style.webkitTransform = 'translateY(0)';
        
        console.log('📱 Keyboard hidden');
      }
    };
    
    // Height change detection
    const checkHeightChange = () => {
      const currentHeight = window.innerHeight;
      const heightDiff = initialHeight - currentHeight;
      
      if (heightDiff > 100) {
        showKeyboard();
      } else if (heightDiff < 50) {
        hideKeyboard();
      }
    };
    
    // Editor focus events
    if (this.editorRoot) {
      this.editorRoot.addEventListener('focusin', () => {
        setTimeout(showKeyboard, 300);
      });
      
      this.editorRoot.addEventListener('focusout', () => {
        setTimeout(() => {
          if (!this.isInputFocused()) {
            hideKeyboard();
          }
        }, 200);
      });
    }
    
    // Global focus events
    window.addEventListener('focusin', (e) => {
      if (e.target && (e.target as Element).matches('input, textarea, [contenteditable]')) {
        setTimeout(showKeyboard, 300);
      }
    });
    
    window.addEventListener('focusout', () => {
      setTimeout(() => {
        if (!this.isInputFocused()) {
          hideKeyboard();
        }
      }, 200);
    });
    
    // Window resize for keyboard detection
    window.addEventListener('resize', () => {
      setTimeout(checkHeightChange, 100);
    });
    
    // Orientation change
    window.addEventListener('orientationchange', () => {
      initialHeight = window.innerHeight;
      hideKeyboard();
    });
  }

  // Debounced update handler
  private debouncedUpdate = (): void => {
    if (!this.isActive) return;
    
    if (this.settings.debounceTime === 0) {
      requestAnimationFrame(() => this.updateToolbarPosition());
    } else {
      if (this.updateTimeout) {
        clearTimeout(this.updateTimeout);
      }
      this.updateTimeout = setTimeout(() => this.updateToolbarPosition(), this.settings.debounceTime);
    }
  };

  // Update toolbar position
  private updateToolbarPosition(): void {
    if (!this.toolbar || !this.isActive) return;
    
    const offset = this.calculateKeyboardOffset();
    
    // Apply transform if offset changed significantly
    if (Math.abs(offset - this.lastKeyboardHeight) > this.settings.threshold) {
      this.applyToolbarTransform(this.toolbar, offset);
      this.lastKeyboardHeight = offset;
      
      console.log('📏 Toolbar position adjusted:', {
        offset: offset,
        visualHeight: window.visualViewport?.height,
        innerHeight: window.innerHeight
      });
    }
    
    // Update keyboard state CSS classes
    this.updateKeyboardClass(offset);
  }

  // Calculate keyboard offset
  private calculateKeyboardOffset(): number {
    let offset = 0;
    
    if (this.hasVisualViewport() && window.visualViewport) {
      const vh = window.visualViewport.height;
      const keyboardHeight = window.innerHeight - vh;
      
      if (keyboardHeight > this.settings.keyboardMin) {
        offset = this.getPlatformSpecificOffset(keyboardHeight);
      }
    } else if (this.isInputFocused()) {
      // Visual Viewport API not supported, use estimation
      offset = 300;
    }
    
    return Math.max(0, offset);
  }

  // Platform-specific offset calculation
  private getPlatformSpecificOffset(keyboardHeight: number): number {
    // iOS PWA status bar height adjustment (20px)
    if (this.isIOS() && this.isPWA()) {
      return keyboardHeight - 20;
    }
    
    // Android PWA navigation bar height detection
    if (this.isAndroid() && this.isPWA()) {
      const navBarHeight = window.outerHeight - window.innerHeight;
      return keyboardHeight - navBarHeight;
    }
    
    // Regular web browser
    return keyboardHeight;
  }

  // Apply toolbar transform
  private applyToolbarTransform(toolbar: HTMLElement, offset: number): void {
    toolbar.style.transform = `translateY(-${offset}px)`;
    toolbar.style.webkitTransform = `translateY(-${offset}px)`;
    toolbar.style.transition = 'transform 0.3s ease-out';
  }

  // Update keyboard CSS classes
  private updateKeyboardClass(offset: number): void {
    if (!this.toolbar) return;
    
    if (offset > 100) {
      document.body.classList.add('keyboard-active');
      this.toolbar.classList.add('keyboard-tracking');
    } else {
      document.body.classList.remove('keyboard-active');
      this.toolbar.classList.remove('keyboard-tracking');
    }
  }

  // Check if input field is focused
  private isInputFocused(): boolean {
    return document.activeElement && 
           document.activeElement.matches('input, textarea, [contenteditable]');
  }

  // Focus out handler
  private handleFocusOut = (): void => {
    setTimeout(() => {
      if (!this.isInputFocused() && this.toolbar) {
        this.toolbar.style.transform = 'translateY(0)';
        this.toolbar.style.webkitTransform = 'translateY(0)';
        document.body.classList.remove('keyboard-active');
        this.toolbar.classList.remove('keyboard-tracking');
        this.lastKeyboardHeight = 0;
      }
    }, 100);
  };

  /**
   * Get current keyboard offset data
   */
  public getKeyboardOffsetData(): KeyboardOffsetData {
    const offset = this.calculateKeyboardOffset();
    return {
      offset,
      visualHeight: window.visualViewport?.height,
      innerHeight: window.innerHeight,
      keyboardHeight: window.innerHeight - (window.visualViewport?.height || window.innerHeight)
    };
  }

  /**
   * Force toolbar position update
   */
  public forceUpdate(): void {
    this.updateToolbarPosition();
  }

  /**
   * Check if keyboard tracking is active
   */
  public isTrackingActive(): boolean {
    return this.isActive;
  }
}