/**
 * Application Use Case: CreatePrizeUseCase
 *
 * Creates a new prize.
 */

import type { IPrizeRepository } from '../../domain/repositories/IPrizeRepository';
import type { PrizeType, Prize } from '../../domain/entities/Prize';
import type { UseCase } from '@core/shared/application/UseCase';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

export interface CreatePrizeInput {
  leagueId: string;
  seasonId: string;
  position: number;
  name: string;
  amount: number;
  type: PrizeType;
  description?: string;
}

export interface CreatePrizeResult {
  prize: Prize;
}

export type CreatePrizeErrorCode = 'PRIZE_ALREADY_EXISTS';

export class CreatePrizeUseCase
  implements UseCase<CreatePrizeInput, void, CreatePrizeErrorCode>
{
  constructor(
    private readonly prizeRepository: IPrizeRepository,
    private readonly output: UseCaseOutputPort<CreatePrizeResult>,
  ) {}

  async execute(input: CreatePrizeInput): Promise<Result<void, ApplicationErrorCode<CreatePrizeErrorCode>>> {
    const { leagueId, seasonId, position, name, amount, type, description } = input;

    const existingPrize = await this.prizeRepository.findByPosition(leagueId, seasonId, position);
    if (existingPrize) {
      return Result.err({ code: 'PRIZE_ALREADY_EXISTS' as const });
    }

    const id = `prize-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    const prize: Prize = {
      id,
      leagueId,
      seasonId,
      position,
      name,
      amount,
      type,
      awarded: false,
      createdAt: new Date(),
      ...(description !== undefined ? { description } : {}),
    };

    const createdPrize = await this.prizeRepository.create(prize);

    this.output.present({ prize: createdPrize });

    return Result.ok(undefined);
  }
}