import type { DataSource } from 'typeorm';

import { JoinRequest } from '@core/racing/domain/entities/JoinRequest';
import type { LeagueMembership } from '@core/racing/domain/entities/LeagueMembership';
import type { LeagueMembershipRepository } from '@core/racing/domain/repositories/LeagueMembershipRepository';

import { LeagueMembershipOrmEntity } from '../entities/LeagueMembershipOrmEntity';
import { LeagueMembershipOrmMapper } from '../mappers/LeagueMembershipOrmMapper';

export class TypeOrmLeagueMembershipRepository implements LeagueMembershipRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: LeagueMembershipOrmMapper,
  ) {}

  async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    const id = `${leagueId}:${driverId}`;
    const entity = await repo.findOne({ where: { id } });
    if (!entity) return null;
    if (entity.status !== 'active' && entity.status !== 'inactive') return null;
    return this.mapper.toDomain(entity);
  }

  async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    const entities = await repo.find({ where: { leagueId, status: 'active' } });
    return entities.map((e) => this.mapper.toDomain(e));
  }

  async getJoinRequests(leagueId: string): Promise<JoinRequest[]> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    const entities = await repo.find({ where: { leagueId, status: 'pending' } });

    return entities.map((e) =>
      JoinRequest.rehydrate({
        id: e.id,
        leagueId: e.leagueId,
        driverId: e.driverId,
        requestedAt: e.joinedAt,
      }),
    );
  }

  async saveMembership(membership: LeagueMembership): Promise<LeagueMembership> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    await repo.save(this.mapper.toOrmEntity(membership));
    return membership;
  }

  async removeMembership(leagueId: string, driverId: string): Promise<void> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    const id = `${leagueId}:${driverId}`;
    await repo.delete({ id });
  }

  async saveJoinRequest(request: JoinRequest): Promise<JoinRequest> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);

    const entity = new LeagueMembershipOrmEntity();
    entity.id = request.id;
    entity.leagueId = request.leagueId.toString();
    entity.driverId = request.driverId.toString();
    entity.role = 'member';
    entity.status = 'pending';
    entity.joinedAt = request.requestedAt.toDate();

    await repo.save(entity);
    return request;
  }

  async removeJoinRequest(requestId: string): Promise<void> {
    const repo = this.dataSource.getRepository(LeagueMembershipOrmEntity);
    await repo.delete({ id: requestId });
  }
}