/**
 * @fileoverview Authentication Manager - UI Integration Component
 * @version 1.0.0
 * @since 2025-08-04
 * @lastUpdated 2025-08-04
 * @module AuthManager
 * @description Component managing authentication UI integration, login modal display, and user status
 * @contributors Claude Code Agent
 * @dependencies Component base class, LoginModal, AppStore, AuthService
 * @requirements REQ-AUTH-014 (Authentication UI integration)
 * @testCoverage Authentication flows, modal management, state synchronization
 */

import { AuthService } from '../services/AuthService';
import { AppStore } from '../store/AppStore';
import { User } from '../types/index';
import { Component } from './Component';
import { LoginModal, LoginModalOptions } from './LoginModal';

/**
 * Authentication Manager Component
 *
 * @description Manages authentication UI integration including login modal,
 *              user status display, and authentication state synchronization.
 *              Provides a centralized way to handle authentication throughout the app.
 *
 * @example
 * ```typescript
 * const authManager = new AuthManager();
 * authManager.mount();
 *
 * // Show login when needed
 * authManager.requireAuthentication();
 *
 * // Check auth status
 * if (authManager.isAuthenticated()) {
 *   // User is logged in
 * }
 * ```
 *
 * @since 2025-08-04
 * @author Claude Code Agent
 * @requirements REQ-AUTH-014 (Authentication UI manager)
 * @accessibility Manages focus and screen reader announcements for auth state changes
 */
export class AuthManager extends Component {
  private static instance: AuthManager;
  private appStore: AppStore;
  private authService: AuthService;
  private loginModal: LoginModal | null = null;
  private unsubscribeStore: (() => void) | null = null;

  // UI Elements
  private userStatusElement: HTMLElement | null = null;
  private loginButton: HTMLElement | null = null;
  private logoutButton: HTMLElement | null = null;
  private userMenuElement: HTMLElement | null = null;
  private guestIndicator: HTMLElement | null = null;

  constructor() {
    // Create auth manager container if it doesn't exist
    if (!document.getElementById('auth-manager')) {
      const container = document.createElement('div');
      container.id = 'auth-manager';
      container.className = 'auth-manager';
      document.body.appendChild(container);
    }

    super('#auth-manager');
    this.appStore = AppStore.getInstance();
    this.authService = AuthService.getInstance();
  }

  /**
   * Get singleton instance
   *
   * @description Returns singleton instance following established pattern
   *
   * @returns {AuthManager} Singleton instance
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  static getInstance(): AuthManager {
    if (!AuthManager.instance) {
      AuthManager.instance = new AuthManager();
    }
    return AuthManager.instance;
  }

  /**
   * Initialize authentication manager
   *
   * @description Sets up authentication UI and state synchronization
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  protected onMount(): void {
    this.setupStoreSubscription();
    this.createAuthUI();
    this.updateAuthUI();
  }

  /**
   * Render authentication UI elements
   *
   * @description Creates the authentication UI components in the header
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  protected render(): void {
    // The auth UI will be injected into existing header elements
    // This method is required by the Component base class
  }

  /**
   * Bind authentication event listeners
   *
   * @description Sets up event listeners for authentication actions
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  protected bindEvents(): void {
    // Login button click
    this.loginButton?.addEventListener('click', () => this.showLoginModal());

    // Logout button click
    this.logoutButton?.addEventListener('click', this.handleLogout.bind(this));

    // User menu toggle
    this.userMenuElement?.addEventListener('click', this.toggleUserMenu.bind(this));
  }

  /**
   * Create authentication UI elements
   *
   * @description Creates and injects auth UI into the header
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private createAuthUI(): void {
    // Find header container (typically in the main navigation)
    const header =
      document.querySelector('header') ||
      document.querySelector('.header') ||
      document.querySelector('nav');

    if (!header) {
      console.warn('No header element found for authentication UI');
      return;
    }

    // Create auth container if it doesn't exist
    let authContainer = header.querySelector('.auth-container');
    if (!authContainer) {
      authContainer = document.createElement('div');
      authContainer.className = 'auth-container flex items-center space-x-3';

      // Insert at the end of header
      header.appendChild(authContainer);
    }

    // Create auth UI elements
    authContainer.innerHTML = `
      <!-- Guest State -->
      <div class="guest-indicator hidden">
        <span class="text-sm text-gray-600 dark:text-gray-400">Guest Mode</span>
      </div>

      <!-- Login Button (when not authenticated) -->
      <button class="login-btn hidden bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
              aria-label="Sign in to your account">
        <span class="flex items-center">
          <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
          </svg>
          Sign In
        </span>
      </button>

      <!-- User Menu (when authenticated) -->
      <div class="user-menu hidden relative">
        <button class="user-menu-toggle flex items-center space-x-2 text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 rounded p-2"
                aria-expanded="false"
                aria-haspopup="true">
          <div class="user-avatar w-8 h-8 bg-blue-600 rounded-full flex items-center justify-center text-white font-medium text-sm">
            <span class="user-initials">U</span>
          </div>
          <span class="user-name hidden sm:block font-medium">User</span>
          <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
          </svg>
        </button>

        <!-- Dropdown Menu -->
        <div class="user-dropdown hidden absolute right-0 mt-2 w-56 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 z-50"
             role="menu"
             aria-orientation="vertical">
          <div class="py-2">
            <!-- User Info -->
            <div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
              <p class="text-sm font-medium text-gray-900 dark:text-white user-display-name">User Name</p>
              <p class="text-sm text-gray-500 dark:text-gray-400 user-email">user@example.com</p>
            </div>

            <!-- Menu Items -->
            <div class="py-1">
              <button class="profile-btn w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
                      role="menuitem">
                <svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
                </svg>
                Profile
              </button>

              <button class="settings-btn w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"
                      role="menuitem">
                <svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
                </svg>
                Settings
              </button>

              <div class="border-t border-gray-200 dark:border-gray-700 my-1"></div>

              <button class="logout-btn w-full text-left px-4 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 flex items-center"
                      role="menuitem">
                <svg class="w-4 h-4 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
                </svg>
                Sign Out
              </button>
            </div>
          </div>
        </div>
      </div>
    `;

    // Cache UI elements
    this.cacheUIElements(authContainer);
  }

  /**
   * Cache UI element references
   *
   * @description Stores references to frequently accessed UI elements
   *
   * @param {Element} container - Auth container element
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private cacheUIElements(container: Element): void {
    this.loginButton = container.querySelector('.login-btn') as HTMLElement;
    this.logoutButton = container.querySelector('.logout-btn') as HTMLElement;
    this.userMenuElement = container.querySelector('.user-menu-toggle') as HTMLElement;
    this.guestIndicator = container.querySelector('.guest-indicator') as HTMLElement;
  }

  /**
   * Setup app store subscription
   *
   * @description Subscribes to app store state changes for auth updates
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private setupStoreSubscription(): void {
    this.unsubscribeStore = this.appStore.subscribe(state => {
      this.updateAuthUI();

      // Handle login modal visibility
      if (state.auth.showLoginModal && !this.loginModal) {
        this.showLoginModal();
      } else if (!state.auth.showLoginModal && this.loginModal) {
        this.hideLoginModal();
      }
    });
  }

  /**
   * Update authentication UI based on current state
   *
   * @description Updates UI elements to reflect current authentication state
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private updateAuthUI(): void {
    const state = this.appStore.getState();
    const { isAuthenticated, user } = state.auth;

    if (isAuthenticated && user) {
      this.showAuthenticatedUI(user);
    } else {
      this.showUnauthenticatedUI();
    }
  }

  /**
   * Show authenticated user UI
   *
   * @description Displays user menu and hides login button
   *
   * @param {User} user - Current authenticated user
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private showAuthenticatedUI(user: User): void {
    // Hide login button and guest indicator
    this.loginButton?.classList.add('hidden');
    this.guestIndicator?.classList.add('hidden');

    // Show user menu
    const userMenu = document.querySelector('.user-menu') as HTMLElement;
    userMenu?.classList.remove('hidden');

    // Update user information
    const userInitials = this.getUserInitials(user.username);
    const userInitialsElement = document.querySelector('.user-initials');
    const userNameElement = document.querySelector('.user-name');
    const userDisplayNameElement = document.querySelector('.user-display-name');
    const userEmailElement = document.querySelector('.user-email');

    if (userInitialsElement) userInitialsElement.textContent = userInitials;
    if (userNameElement) userNameElement.textContent = user.username;
    if (userDisplayNameElement) userDisplayNameElement.textContent = user.username;
    if (userEmailElement) userEmailElement.textContent = user.email || '';

    // Announce to screen readers
    this.announceToScreenReader(`Signed in as ${user.username}`);
  }

  /**
   * Show unauthenticated UI
   *
   * @description Displays login button and hides user menu
   *
   * @since 2025-08-04
   * @author Claude Code Author
   */
  private showUnauthenticatedUI(): void {
    // Show login button
    this.loginButton?.classList.remove('hidden');

    // Hide user menu
    const userMenu = document.querySelector('.user-menu') as HTMLElement;
    userMenu?.classList.add('hidden');

    // Hide guest indicator by default
    this.guestIndicator?.classList.add('hidden');
  }

  /**
   * Show guest mode UI
   *
   * @description Displays guest mode indicator
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private showGuestUI(): void {
    this.loginButton?.classList.add('hidden');
    this.guestIndicator?.classList.remove('hidden');

    const userMenu = document.querySelector('.user-menu') as HTMLElement;
    userMenu?.classList.add('hidden');

    this.announceToScreenReader('Continuing in guest mode');
  }

  /**
   * Get user initials for avatar
   *
   * @description Generates user initials from username
   *
   * @param {string} username - User's username
   * @returns {string} User initials (max 2 characters)
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private getUserInitials(username: string): string {
    if (!username) return 'U';

    const parts = username.split(/[\s@_.-]+/);
    if (parts.length >= 2) {
      return (parts[0][0] + parts[1][0]).toUpperCase();
    }

    return username.substring(0, 2).toUpperCase();
  }

  /**
   * Show login modal
   *
   * @description Creates and displays the login modal
   *
   * @param {LoginModalOptions} options - Modal options
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  public showLoginModal(options: LoginModalOptions = {}): void {
    if (this.loginModal) return;

    const modalOptions: LoginModalOptions = {
      showRegisterLink: true,
      allowGuestMode: true,
      onSuccess: user => {
        if (user) {
          this.announceToScreenReader(`Welcome back, ${user.username}!`);
        } else {
          this.showGuestUI();
        }
        this.hideLoginModal();
        options.onSuccess?.(user);
      },
      onCancel: () => {
        this.hideLoginModal();
        options.onCancel?.();
      },
      ...options,
    };

    this.loginModal = new LoginModal(modalOptions);
    this.loginModal.show();
    this.appStore.showLoginModal();
  }

  /**
   * Hide login modal
   *
   * @description Hides and cleans up the login modal
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  public hideLoginModal(): void {
    if (this.loginModal) {
      this.loginModal.hide();
      this.loginModal = null;
    }
    this.appStore.hideLoginModal();
  }

  /**
   * Handle logout action
   *
   * @description Logs out user and updates UI
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private async handleLogout(): Promise<void> {
    try {
      await this.appStore.logout();
      this.announceToScreenReader('You have been signed out');

      // Close user menu
      this.closeUserMenu();
    } catch (error) {
      console.error('Logout failed:', error);
      this.announceToScreenReader('Logout failed. Please try again.');
    }
  }

  /**
   * Toggle user menu dropdown
   *
   * @description Shows/hides the user dropdown menu
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private toggleUserMenu(): void {
    const dropdown = document.querySelector('.user-dropdown') as HTMLElement;
    const toggle = this.userMenuElement;

    if (!dropdown || !toggle) return;

    const isOpen = !dropdown.classList.contains('hidden');

    if (isOpen) {
      this.closeUserMenu();
    } else {
      this.openUserMenu();
    }
  }

  /**
   * Open user menu dropdown
   *
   * @description Opens the user dropdown menu with accessibility
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   * @accessibility Updates aria-expanded and manages focus
   */
  private openUserMenu(): void {
    const dropdown = document.querySelector('.user-dropdown') as HTMLElement;
    const toggle = this.userMenuElement;

    if (!dropdown || !toggle) return;

    dropdown.classList.remove('hidden');
    toggle.setAttribute('aria-expanded', 'true');

    // Focus first menu item
    const firstMenuItem = dropdown.querySelector('[role="menuitem"]') as HTMLElement;
    firstMenuItem?.focus();

    // Close on outside click
    setTimeout(() => {
      document.addEventListener('click', this.handleOutsideClick.bind(this));
    }, 0);
  }

  /**
   * Close user menu dropdown
   *
   * @description Closes the user dropdown menu
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   * @accessibility Updates aria-expanded and manages focus
   */
  private closeUserMenu(): void {
    const dropdown = document.querySelector('.user-dropdown') as HTMLElement;
    const toggle = this.userMenuElement;

    if (!dropdown || !toggle) return;

    dropdown.classList.add('hidden');
    toggle.setAttribute('aria-expanded', 'false');

    document.removeEventListener('click', this.handleOutsideClick.bind(this));
  }

  /**
   * Handle clicks outside user menu
   *
   * @description Closes user menu when clicking outside
   *
   * @param {Event} event - Click event
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  private handleOutsideClick(event: Event): void {
    const userMenu = document.querySelector('.user-menu');
    if (!userMenu?.contains(event.target as Node)) {
      this.closeUserMenu();
    }
  }

  /**
   * Require authentication
   *
   * @description Forces user to authenticate or shows login modal
   *
   * @returns {Promise<boolean>} Whether authentication was successful
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  public async requireAuthentication(): Promise<boolean> {
    if (this.appStore.isAuthenticated()) {
      return true;
    }

    return new Promise(resolve => {
      this.showLoginModal({
        onSuccess: user => {
          resolve(!!user);
        },
        onCancel: () => {
          resolve(false);
        },
      });
    });
  }

  /**
   * Check if user is authenticated
   *
   * @description Returns current authentication status
   *
   * @returns {boolean} Authentication status
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  public isAuthenticated(): boolean {
    return this.appStore.isAuthenticated();
  }

  /**
   * Get current user
   *
   * @description Returns current authenticated user
   *
   * @returns {User | null} Current user
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  public getCurrentUser(): User | null {
    return this.appStore.getCurrentUser();
  }

  /**
   * Announce message to screen readers
   *
   * @description Creates temporary element for screen reader announcements
   *
   * @param {string} message - Message to announce
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   * @accessibility Provides screen reader feedback
   */
  private announceToScreenReader(message: string): void {
    const announcement = document.createElement('div');
    announcement.setAttribute('aria-live', 'polite');
    announcement.setAttribute('aria-atomic', 'true');
    announcement.className = 'sr-only';
    announcement.textContent = message;

    document.body.appendChild(announcement);

    setTimeout(() => {
      document.body.removeChild(announcement);
    }, 1000);
  }

  /**
   * Clean up resources
   *
   * @description Removes event listeners and subscriptions
   *
   * @since 2025-08-04
   * @author Claude Code Agent
   */
  protected onUnmount(): void {
    this.unsubscribeStore?.();
    document.removeEventListener('click', this.handleOutsideClick.bind(this));

    if (this.loginModal) {
      this.loginModal.hide();
      this.loginModal = null;
    }
  }
}
