import { Result } from '@core/shared/application/Result';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import type { Team } from '../../domain/entities/Team';
import type { ITeamMembershipRepository } from '../../domain/repositories/ITeamMembershipRepository';
import type { ITeamRepository } from '../../domain/repositories/ITeamRepository';

export type UpdateTeamInput = {
  teamId: string;
  updatedBy: string;
  updates: {
    name?: string;
    tag?: string;
    description?: string;
    leagues?: string[];
  };
};

export type UpdateTeamResult = {
  team: Team;
};

export type UpdateTeamErrorCode = 'TEAM_NOT_FOUND' | 'PERMISSION_DENIED' | 'REPOSITORY_ERROR';

export class UpdateTeamUseCase {
  constructor(
    private readonly teamRepository: ITeamRepository,
    private readonly membershipRepository: ITeamMembershipRepository,
    private readonly output: UseCaseOutputPort<UpdateTeamResult>,
  ) {}

  async execute(
    command: UpdateTeamInput,
  ): Promise<Result<void, ApplicationErrorCode<UpdateTeamErrorCode, { message: string }>>> {
    try {
      const { teamId, updatedBy, updates } = command;

      const updaterMembership = await this.membershipRepository.getMembership(teamId, updatedBy);
      if (!updaterMembership || (updaterMembership.role !== 'owner' && updaterMembership.role !== 'manager')) {
        return Result.err({
          code: 'PERMISSION_DENIED',
          details: {
            message: 'User does not have permission to update this team',
          },
        });
      }

      const existing = await this.teamRepository.findById(teamId);
      if (!existing) {
        return Result.err({
          code: 'TEAM_NOT_FOUND',
          details: {
            message: 'Team not found',
          },
        });
      }

      const updated = existing.update({
        ...(updates.name !== undefined && { name: updates.name }),
        ...(updates.tag !== undefined && { tag: updates.tag }),
        ...(updates.description !== undefined && { description: updates.description }),
        ...(updates.leagues !== undefined && { leagues: updates.leagues }),
      });

      await this.teamRepository.update(updated);

      this.output.present({ team: updated });

      return Result.ok(undefined);
    } catch (err) {
      const error = err as { message?: string } | undefined;

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: {
          message: error?.message ?? 'Failed to update team',
        },
      });
    }
  }
}
