import { AuthenticationState } from '../../domain/value-objects/AuthenticationState';
import type { Logger } from '@core/shared/application';
import { Result } from '@gridpilot/shared/application/Result';
import type { AuthenticationServicePort } from '../ports/AuthenticationServicePort';
import { SessionLifetime } from '../../domain/value-objects/SessionLifetime';
import type { SessionValidatorPort } from '../ports/SessionValidatorPort';

/**
 * Use case for checking if the user has a valid iRacing session.
 *
 * This validates the session before automation starts, allowing
 * the system to prompt for re-authentication if needed.
 *
 * Implements hybrid validation strategy:
 * - File-based validation (fast, always executed)
 * - Optional server-side validation (slow, requires network)
 */
export class CheckAuthenticationUseCase {
  constructor(
    private readonly logger: Logger,
    private readonly authService: AuthenticationServicePort,
    private readonly sessionValidator?: SessionValidatorPort
  ) {}

  /**
   * Execute the authentication check.
   *
   * @param options Optional configuration for validation
   * @returns Result containing the current AuthenticationState
   */
  async execute(options?: {
    requireServerValidation?: boolean;
    verifyPageContent?: boolean;
  }): Promise<Result<AuthenticationState>> {
    this.logger.debug('Executing CheckAuthenticationUseCase', { options });
    try {
      // Step 1: File-based validation (fast)
      this.logger.debug('Performing file-based authentication check.');
      const fileResult = await this.authService.checkSession();
      if (fileResult.isErr()) {
        this.logger.error('File-based authentication check failed.', fileResult.unwrapErr());
        return fileResult;
      }
      this.logger.info('File-based authentication check succeeded.');

      const fileState = fileResult.unwrap();
      this.logger.debug(`File-based authentication state: ${fileState}`);

      // Step 2: Check session expiry if authenticated
      if (fileState === AuthenticationState.AUTHENTICATED) {
        this.logger.debug('Session is authenticated, checking expiry.');
        const expiryResult = await this.authService.getSessionExpiry();
        if (expiryResult.isErr()) {
          this.logger.warn('Could not retrieve session expiry, proceeding with file-based state.', { error: expiryResult.unwrapErr() });
          // Don't fail completely if we can't get expiry, use file-based state
          return Result.ok(fileState);
        }

        const expiry = expiryResult.unwrap();
        if (expiry !== null) {
          try {
            const sessionLifetime = new SessionLifetime(expiry);
            if (sessionLifetime.isExpired()) {
              this.logger.info('Session has expired based on lifetime.');
              return Result.ok(AuthenticationState.EXPIRED);
            }
            this.logger.debug('Session is not expired.');
          } catch (error) {
            this.logger.error('Invalid expiry date encountered, treating session as expired.', error as Error, { expiry });
            // Invalid expiry date, treat as expired for safety
            return Result.ok(AuthenticationState.EXPIRED);
          }
        }
      }

      // Step 3: Optional page content verification
      if (options?.verifyPageContent && fileState === AuthenticationState.AUTHENTICATED) {
        this.logger.debug('Performing optional page content verification.');
        const pageResult = await this.authService.verifyPageAuthentication();
        
        if (pageResult.isOk()) {
          const browserState = pageResult.unwrap();
          // If cookies valid but page shows login UI, session is expired
          if (!browserState.isFullyAuthenticated()) {
            this.logger.info('Page content verification indicated session expired.');
            return Result.ok(AuthenticationState.EXPIRED);
          }
          this.logger.info('Page content verification succeeded.');
        } else {
          this.logger.warn('Page content verification failed, proceeding with file-based state.', { error: pageResult.unwrapErr() });
        }
        // Don't block on page verification errors, continue with file-based state
      }

      // Step 4: Optional server-side validation
      if (this.sessionValidator && fileState === AuthenticationState.AUTHENTICATED) {
        this.logger.debug('Performing optional server-side validation.');
        const serverResult = await this.sessionValidator.validateSession();
        
        // Don't block on server validation errors
        if (serverResult.isOk()) {
          const isValid = serverResult.unwrap();
          if (!isValid) {
            this.logger.info('Server-side validation indicated session expired.');
            return Result.ok(AuthenticationState.EXPIRED);
          }
          this.logger.info('Server-side validation succeeded.');
        } else {
          this.logger.warn('Server-side validation failed, proceeding with file-based state.', { error: serverResult.unwrapErr() });
        }
      }
      this.logger.info(`CheckAuthenticationUseCase completed successfully with state: ${fileState}`);
      return Result.ok(fileState);
    } catch (error) {
      this.logger.error('An unexpected error occurred during authentication check.', error as Error);
      throw error;
    }
  }
}