import type { Logger } from '@core/shared/application';
import type { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
import { LeagueMembership, type MembershipRole, type MembershipStatus } from '../../domain/entities/LeagueMembership';
import type { AsyncUseCase } from '@core/shared/application';
import { Result as SharedResult } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

import type { JoinLeagueCommandDTO } from '../dto/JoinLeagueCommandDTO';

type JoinLeagueErrorCode = 'ALREADY_MEMBER' | 'REPOSITORY_ERROR';

type JoinLeagueApplicationError = ApplicationErrorCode<JoinLeagueErrorCode, { message: string }>;

export class JoinLeagueUseCase implements AsyncUseCase<JoinLeagueCommandDTO, LeagueMembership, JoinLeagueErrorCode> {
  constructor(
    private readonly membershipRepository: ILeagueMembershipRepository,
    private readonly logger: Logger,
  ) {}

  /**
   * Joins a driver to a league as an active member.
   *
   * Mirrors the behavior of the legacy joinLeague function:
   * - Returns error when membership already exists for this league/driver.
   * - Creates a new active membership with role "member" and current timestamp.
   */
  async execute(command: JoinLeagueCommandDTO): Promise<SharedResult<LeagueMembership, JoinLeagueApplicationError>> {
    this.logger.debug('Attempting to join league', { command });
    const { leagueId, driverId } = command;

    try {
      const existing = await this.membershipRepository.getMembership(leagueId, driverId);
      if (existing) {
        this.logger.warn('Driver already a member or has pending request', { leagueId, driverId });
        return SharedResult.err({ code: 'ALREADY_MEMBER', details: { message: 'Already a member or have a pending request' } });
      }

      const membership = LeagueMembership.create({
        leagueId,
        driverId,
        role: 'member' as MembershipRole,
        status: 'active' as MembershipStatus,
      });

      const savedMembership = await this.membershipRepository.saveMembership(membership);
      this.logger.info('Successfully joined league', { membershipId: savedMembership.id });
      return SharedResult.ok(savedMembership);
    } catch (error) {
      this.logger.error('Failed to join league due to an unexpected error', error instanceof Error ? error : new Error('Unknown error'));
      return SharedResult.err({ code: 'REPOSITORY_ERROR', details: { message: error instanceof Error ? error.message : 'Unknown error' } });
    }
  }
}