import { EmailAddress } from '@core/identity/domain/value-objects/EmailAddress';
import { UserId } from '@core/identity/domain/value-objects/UserId';
import { User } from '@core/identity/domain/entities/User';
import { IAuthRepository } from '@core/identity/domain/repositories/IAuthRepository';
import { IPasswordHashingService } from '@core/identity/domain/services/PasswordHashingService';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { UseCaseOutputPort, Logger, UseCase } from '@core/shared/application';

export type DemoLoginInput = {
  role: 'driver' | 'sponsor' | 'league-owner' | 'league-steward' | 'league-admin' | 'system-owner' | 'super-admin';
};

export type DemoLoginResult = {
  user: User;
};

export type DemoLoginErrorCode = 'DEMO_NOT_ALLOWED' | 'REPOSITORY_ERROR';

export type DemoLoginApplicationError = ApplicationErrorCode<DemoLoginErrorCode, { message: string }>;

/**
 * Application Use Case: DemoLoginUseCase
 *
 * Provides demo login functionality for development environments.
 * Creates demo users with predefined credentials.
 * 
 * ⚠️ DEVELOPMENT ONLY - Should be disabled in production
 */
export class DemoLoginUseCase implements UseCase<DemoLoginInput, void, DemoLoginErrorCode> {
  constructor(
    private readonly authRepo: IAuthRepository,
    private readonly passwordService: IPasswordHashingService,
    private readonly logger: Logger,
    private readonly output: UseCaseOutputPort<DemoLoginResult>,
  ) {}

  async execute(input: DemoLoginInput): Promise<Result<void, DemoLoginApplicationError>> {
    // Security check: Only allow in development
    if (process.env.NODE_ENV !== 'development' && process.env.ALLOW_DEMO_LOGIN !== 'true') {
      return Result.err({
        code: 'DEMO_NOT_ALLOWED',
        details: { message: 'Demo login is only available in development environment' },
      });
    }

    try {
      // Generate demo user email and display name based on role
      const roleConfig = {
        'driver': { email: 'demo.driver@example.com', name: 'John Demo', primaryDriverId: true },
        'sponsor': { email: 'demo.sponsor@example.com', name: 'Jane Sponsor', primaryDriverId: false },
        'league-owner': { email: 'demo.owner@example.com', name: 'Alex Owner', primaryDriverId: true },
        'league-steward': { email: 'demo.steward@example.com', name: 'Sam Steward', primaryDriverId: true },
        'league-admin': { email: 'demo.admin@example.com', name: 'Taylor Admin', primaryDriverId: true },
        'system-owner': { email: 'demo.systemowner@example.com', name: 'System Owner', primaryDriverId: true },
        'super-admin': { email: 'demo.superadmin@example.com', name: 'Super Admin', primaryDriverId: true },
      };

      const config = roleConfig[input.role];
      const emailVO = EmailAddress.create(config.email);

      // Check if demo user already exists
      let user = await this.authRepo.findByEmail(emailVO);

      if (!user) {
        // Create new demo user
        this.logger.info('[DemoLoginUseCase] Creating new demo user', { role: input.role });

        const userId = UserId.create();
        
        // Use a fixed demo password and hash it
        const demoPassword = 'Demo1234!';
        const hashedPassword = await this.passwordService.hash(demoPassword);
        
        // Import PasswordHash and create proper object
        const passwordHashModule = await import('@core/identity/domain/value-objects/PasswordHash');
        const passwordHash = passwordHashModule.PasswordHash.fromHash(hashedPassword);

        const userProps: any = {
          id: userId,
          displayName: config.name,
          email: config.email,
          passwordHash,
        };
        
        if (config.primaryDriverId) {
          userProps.primaryDriverId = `demo-${input.role}-${userId.value}`;
          // Add avatar URL for demo users with primary driver
          // Use the same format as seeded drivers: /media/default/neutral-default-avatar
          userProps.avatarUrl = '/media/default/neutral-default-avatar';
        }

        user = User.create(userProps);

        await this.authRepo.save(user);
      } else {
        this.logger.info('[DemoLoginUseCase] Using existing demo user', {
          role: input.role,
          userId: user.getId().value
        });
      }

      this.output.present({ user });

      return Result.ok(undefined);
    } catch (error) {
      const message =
        error instanceof Error && error.message
          ? error.message
          : 'Failed to execute DemoLoginUseCase';

      this.logger.error('DemoLoginUseCase.execute failed', error instanceof Error ? error : undefined, {
        input,
      });

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message },
      });
    }
  }
}