import type { IAuthRepository, ITrustRepository, Credentials, UserSession, AuthConfig } from '../interfaces';
import type { AuthResult } from '../entities';

/**
 * Login Use Case - Pure business logic
 * Orchestrates the login flow including risk assessment and DPoP initialization
 * 
 * Features implemented (per FRD):
 * - F.ID.001: Login flows
 * - F.ID.004: DPoP integration
 * - Risk-adaptive authentication
 * - Step-up MFA based on risk score
 */
export class LoginUseCase {
  constructor(
    private authRepository: IAuthRepository,
    private trustRepository: ITrustRepository,
    private config: AuthConfig
  ) {}

  /**
   * Execute login flow with risk assessment
   */
  async execute(credentials: Credentials): Promise<AuthResult> {
    try {
      // 1. Risk Assessment (F.TR.004 from Trust SDK)
      const { score: riskScore, signals } = await this.trustRepository.calculateRiskScore();
      
      // 2. Initialize DPoP (F.ID.004 / F.SC.004)
      const publicKey = await this.authRepository.initializeDPoP();
      
      // 3. Attempt authentication
      const session = await this.authRepository.exchangeCredentialsForToken(credentials, publicKey);
      
      // 4. Enhance session with risk information
      const enhancedSession: UserSession = {
        ...session,
        riskScore,
        requiresStepUp: this.shouldRequireStepUp(riskScore, signals)
      };
      
      // 5. Store session
      await this.authRepository.storeSession(enhancedSession);
      
      // 6. Check if step-up authentication is required
      if (enhancedSession.requiresStepUp) {
        return {
          success: true,
          session: enhancedSession,
          requiresVerification: true,
          verificationMethod: this.determineStepUpMethod(signals),
          nextSteps: ['Complete additional verification to proceed']
        };
      }
      
      // 7. Enable Remember Me if configured
      if (this.config.rememberMeDays > 0) {
        await this.authRepository.enableRememberMe(this.config.rememberMeDays);
      }
      
      return {
        success: true,
        session: enhancedSession
      };
      
    } catch (error) {
      return this.handleLoginError(error);
    }
  }

  /**
   * Biometric login flow
   */
  async executeWithBiometrics(biometricSignature: string, deviceId: string): Promise<AuthResult> {
    const credentials: Credentials = {
      identifier: 'biometric',
      biometricSignature,
      deviceId
    };
    
    return this.execute(credentials);
  }

  /**
   * Magic link login flow (F.ID.006)
   */
  async executeWithMagicLink(token: string, nonce: string): Promise<AuthResult> {
    try {
      const session = await this.authRepository.verifyMagicLink(token, nonce);
      await this.authRepository.storeSession(session);
      
      return {
        success: true,
        session
      };
    } catch (error) {
      return this.handleLoginError(error);
    }
  }

  /**
   * Federated login flow (F.ID.007)
   */
  async executeWithProvider(provider: 'google' | 'apple', token: string): Promise<AuthResult> {
    try {
      const session = await this.authRepository.authenticateWithProvider(provider, token);
      await this.authRepository.storeSession(session);
      
      return {
        success: true,
        session
      };
    } catch (error) {
      return this.handleLoginError(error);
    }
  }

  private shouldRequireStepUp(riskScore: number, signals: Record<string, any>): boolean {
    // Risk-based step-up logic
    if (riskScore > 75) return true;
    if (signals.isRooted || signals.isEmulator) return true;
    if (signals.attestationFailed) return true;
    if (signals.geoDeviation && riskScore > 50) return true;
    
    return false;
  }

  private determineStepUpMethod(signals: Record<string, any>) {
    // Determine the most appropriate step-up method based on risk signals
    if (signals.suspiciousLocation) {
      return { type: 'otp' as const, target: 'phone' };
    }
    
    if (signals.newDevice) {
      return { type: 'email' as const, target: 'email' };
    }
    
    // Default to biometric if available
    return { type: 'biometric' as const };
  }

  private handleLoginError(error: any): AuthResult {
    console.error('Login failed:', error);
    
    // Map specific errors to user-friendly messages
    if (error.code === 'INVALID_CREDENTIALS') {
      return {
        success: false,
        errorCode: 'INVALID_CREDENTIALS',
        errorMessage: 'Invalid email or password'
      };
    }
    
    if (error.code === 'ACCOUNT_LOCKED') {
      return {
        success: false,
        errorCode: 'ACCOUNT_LOCKED',
        errorMessage: 'Account is temporarily locked due to multiple failed attempts'
      };
    }
    
    if (error.code === 'VERIFICATION_REQUIRED') {
      return {
        success: false,
        requiresVerification: true,
        verificationMethod: error.verificationMethod,
        errorMessage: 'Account verification required'
      };
    }
    
    return {
      success: false,
      errorCode: 'UNKNOWN_ERROR',
      errorMessage: 'An unexpected error occurred'
    };
  }
}