/**
 * Query: GetTeamRatingLedgerQuery
 * 
 * Paginated/filtered query for team rating events (ledger).
 * Mirrors user slice 6 pattern but for teams.
 */

import { PaginatedQueryOptions, TeamRatingEventFilter, TeamRatingEventRepository } from '../../domain/repositories/TeamRatingEventRepository';
import { PaginatedTeamLedgerResult, TeamLedgerEntryDto, TeamLedgerFilter } from '../dtos/TeamLedgerEntryDto';

export interface GetTeamRatingLedgerQuery {
  teamId: string;
  limit?: number;
  offset?: number;
  filter?: TeamLedgerFilter;
}

export class GetTeamRatingLedgerQueryHandler {
  constructor(
    private readonly ratingEventRepo: TeamRatingEventRepository
  ) {}

  async execute(query: GetTeamRatingLedgerQuery): Promise<PaginatedTeamLedgerResult> {
    const { teamId, limit = 20, offset = 0, filter } = query;

    // Build repo options
    const repoOptions: PaginatedQueryOptions = {
      limit,
      offset,
    };

    // Add filter if provided
    if (filter) {
      const ratingEventFilter: TeamRatingEventFilter = {};
      
      if (filter.dimensions) {
        ratingEventFilter.dimensions = filter.dimensions;
      }
      if (filter.sourceTypes) {
        ratingEventFilter.sourceTypes = filter.sourceTypes;
      }
      if (filter.from) {
        ratingEventFilter.from = new Date(filter.from);
      }
      if (filter.to) {
        ratingEventFilter.to = new Date(filter.to);
      }
      if (filter.reasonCodes) {
        ratingEventFilter.reasonCodes = filter.reasonCodes;
      }

      repoOptions.filter = ratingEventFilter;
    }

    // Query repository
    const result = await this.ratingEventRepo.findEventsPaginated(teamId, repoOptions);

    // Convert domain entities to DTOs
    const entries: TeamLedgerEntryDto[] = result.items.map(event => {
      const source: { type: 'race' | 'penalty' | 'vote' | 'adminAction' | 'manualAdjustment'; id?: string } = {
        type: event.source.type,
      };
      if (event.source.id !== undefined) {
        source.id = event.source.id;
      }

      const reason: { code: string; description?: string } = {
        code: event.reason.code,
      };
      if (event.reason.description !== undefined) {
        reason.description = event.reason.description;
      }

      const dto: TeamLedgerEntryDto = {
        id: event.id.value,
        teamId: event.teamId,
        dimension: event.dimension.value,
        delta: event.delta.value,
        occurredAt: event.occurredAt.toISOString(),
        createdAt: event.createdAt.toISOString(),
        source,
        reason,
        visibility: {
          public: event.visibility.public,
        },
      };
      if (event.weight !== undefined) {
        dto.weight = event.weight;
      }
      return dto;
    });

    const nextOffset = result.nextOffset !== undefined ? result.nextOffset : null;

    return {
      entries,
      pagination: {
        total: result.total,
        limit: result.limit,
        offset: result.offset,
        hasMore: result.hasMore,
        nextOffset,
      },
    };
  }
}