/**
 * Application Use Case: UpsertMembershipFeeUseCase
 *
 * Creates or updates membership fee configuration.
 */

import type { IMembershipFeeRepository } from '../../domain/repositories/IMembershipFeeRepository';
import type { MembershipFeeType, MembershipFee } from '../../domain/entities/MembershipFee';
import type { UseCase } from '@core/shared/application/UseCase';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import { Result } from '@core/shared/application/Result';

export interface UpsertMembershipFeeInput {
  leagueId: string;
  seasonId?: string;
  type: MembershipFeeType;
  amount: number;
}

export interface UpsertMembershipFeeResult {
  fee: MembershipFee;
}

export type UpsertMembershipFeeErrorCode = never;

export class UpsertMembershipFeeUseCase
  implements UseCase<UpsertMembershipFeeInput, void, UpsertMembershipFeeErrorCode>
{
  constructor(
    private readonly membershipFeeRepository: IMembershipFeeRepository,
    private readonly output: UseCaseOutputPort<UpsertMembershipFeeResult>,
  ) {}

  async execute(input: UpsertMembershipFeeInput): Promise<Result<void, never>> {
    const { leagueId, seasonId, type, amount } = input;

    let existingFee = await this.membershipFeeRepository.findByLeagueId(leagueId);

    let fee: MembershipFee;
    if (existingFee) {
      existingFee.type = type;
      existingFee.amount = amount;
      if (seasonId !== undefined) existingFee.seasonId = seasonId;
      existingFee.enabled = amount > 0;
      existingFee.updatedAt = new Date();
      fee = await this.membershipFeeRepository.update(existingFee);
    } else {
      const id = `fee-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      const newFee: MembershipFee = {
        id,
        leagueId,
        type,
        amount,
        enabled: amount > 0,
        createdAt: new Date(),
        updatedAt: new Date(),
        ...(seasonId !== undefined ? { seasonId } : {}),
      };
      fee = await this.membershipFeeRepository.create(newFee);
    }

    this.output.present({ fee });

    return Result.ok(undefined);
  }
}