/**
 * Token Detector
 * 
 * Watches for page changes and session events in the Filevine SPA.
 */

export class TokenDetector {
  constructor() {
    this.observers = [];
    this.lastUrl = window.location.href;
  }

  /**
   * Watch for SPA navigation and DOM changes that might indicate auth changes
   */
  watchForChanges(callback) {
    // URL change detection (SPA navigation)
    this.setupUrlWatcher(callback);

    // DOM mutation observer for auth-related changes
    this.setupDomObserver(callback);

    // Storage event listener
    this.setupStorageWatcher(callback);
  }

  /**
   * Watch for URL changes (pushState/popState)
   */
  setupUrlWatcher(callback) {
    // Override pushState and replaceState
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = (...args) => {
      originalPushState.apply(history, args);
      this.onUrlChange(callback);
    };

    history.replaceState = (...args) => {
      originalReplaceState.apply(history, args);
      this.onUrlChange(callback);
    };

    // Listen for popstate (back/forward navigation)
    window.addEventListener('popstate', () => {
      this.onUrlChange(callback);
    });
  }

  /**
   * Handle URL changes
   */
  onUrlChange(callback) {
    const currentUrl = window.location.href;
    if (currentUrl !== this.lastUrl) {
      this.lastUrl = currentUrl;
      
      // Debounce callback
      clearTimeout(this.urlChangeTimeout);
      this.urlChangeTimeout = setTimeout(() => {
        callback('url_change');
      }, 500);
    }
  }

  /**
   * Watch DOM for auth-related changes
   */
  setupDomObserver(callback) {
    // Watch for login/logout DOM patterns
    const observer = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        // Check for auth-related elements being added/removed
        if (this.isAuthRelatedMutation(mutation)) {
          clearTimeout(this.domChangeTimeout);
          this.domChangeTimeout = setTimeout(() => {
            callback('dom_change');
          }, 1000);
          break;
        }
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: false
    });

    this.observers.push(observer);
  }

  /**
   * Check if mutation is auth-related
   */
  isAuthRelatedMutation(mutation) {
    const authPatterns = [
      'login',
      'logout',
      'auth',
      'session',
      'user-menu',
      'profile'
    ];

    for (const node of mutation.addedNodes) {
      if (node.nodeType !== Node.ELEMENT_NODE) continue;
      
      const html = node.outerHTML?.toLowerCase() || '';
      const classes = node.className?.toLowerCase() || '';
      const id = node.id?.toLowerCase() || '';

      for (const pattern of authPatterns) {
        if (html.includes(pattern) || classes.includes(pattern) || id.includes(pattern)) {
          return true;
        }
      }
    }

    return false;
  }

  /**
   * Watch for storage changes
   */
  setupStorageWatcher(callback) {
    window.addEventListener('storage', (event) => {
      // Check if auth-related key changed
      const authKeys = ['access_token', 'fv_auth', 'oidc.user', 'auth', 'token'];
      
      if (authKeys.some(key => event.key?.includes(key))) {
        callback('storage_change');
      }
    });
  }

  /**
   * Detect if user is logged in based on page content
   */
  isLoggedIn() {
    // Check for common logged-in indicators
    const indicators = [
      // User menu present
      document.querySelector('[class*="user-menu"]'),
      document.querySelector('[class*="profile"]'),
      document.querySelector('[data-testid="user-avatar"]'),
      // Project list present
      document.querySelector('[class*="project-list"]'),
      // Main app shell (not login page)
      document.querySelector('[class*="app-container"]'),
      document.querySelector('[class*="main-content"]')
    ];

    // Check for login page indicators (negative)
    const loginIndicators = [
      document.querySelector('form[action*="login"]'),
      document.querySelector('input[type="password"]'),
      document.querySelector('[class*="login-form"]')
    ];

    const hasAppIndicators = indicators.some(el => el !== null);
    const hasLoginIndicators = loginIndicators.some(el => el !== null);

    return hasAppIndicators && !hasLoginIndicators;
  }

  /**
   * Get current page context
   */
  getPageContext() {
    const url = new URL(window.location.href);

    // Extract project ID from URL
    const projectMatch = url.pathname.match(/\/projects?\/(\d+)/i);
    const projectId = projectMatch ? projectMatch[1] : null;

    // Extract project type ID from URL (for custom project type pages)
    // URL format: https://product.filevineapp.com/api/advanced/orgs/{orgId}/customProjectTypes/{projectTypeId}
    const projectTypeMatch = url.pathname.match(/\/customProjectTypes\/(\d+)/i);
    const projectTypeId = projectTypeMatch ? projectTypeMatch[1] : null;

    // Extract org ID from URL
    const orgMatch = url.pathname.match(/\/orgs\/(\d+)/i);
    const orgId = orgMatch ? orgMatch[1] : null;

    // Determine page type
    let pageType = 'unknown';
    if (url.pathname.includes('/customProjectTypes')) pageType = 'customProjectType';
    else if (url.pathname.includes('/project')) pageType = 'project';
    else if (url.pathname.includes('/document')) pageType = 'document';
    else if (url.pathname.includes('/contact')) pageType = 'contact';
    else if (url.pathname.includes('/search')) pageType = 'search';
    else if (url.pathname === '/' || url.pathname.includes('/dashboard')) pageType = 'dashboard';

    return {
      url: url.href,
      pathname: url.pathname,
      pageType,
      projectId,
      projectTypeId,
      orgId,
      isLoggedIn: this.isLoggedIn()
    };
  }

  /**
   * Cleanup observers
   */
  disconnect() {
    this.observers.forEach(observer => observer.disconnect());
    this.observers = [];
    clearTimeout(this.urlChangeTimeout);
    clearTimeout(this.domChangeTimeout);
  }
}
