/**
 * Application Use Case: GetPendingSponsorshipRequestsUseCase
 *
 * Retrieves pending sponsorship requests for an entity owner to review.
 */

import type { ISponsorshipRequestRepository } from '../../domain/repositories/ISponsorshipRequestRepository';
import type { ISponsorRepository } from '../../domain/repositories/ISponsorRepository';
import type { SponsorableEntityType, SponsorshipRequest } from '../../domain/entities/SponsorshipRequest';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import { Result } from '@core/shared/application/Result';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
import type { Sponsor } from '../../domain/entities/sponsor/Sponsor';
import { Money } from '../../domain/value-objects/Money';

export interface GetPendingSponsorshipRequestsInput {
  entityType: SponsorableEntityType;
  entityId: string;
}

export interface PendingSponsorshipRequestFinancials {
  offeredAmount: Money;
  platformFee: Money;
  netAmount: Money;
}

export interface PendingSponsorshipRequestSummary {
  request: SponsorshipRequest;
  sponsor: Sponsor | null;
  financials: PendingSponsorshipRequestFinancials;
}

export interface GetPendingSponsorshipRequestsResult {
  entityType: SponsorableEntityType;
  entityId: string;
  requests: PendingSponsorshipRequestSummary[];
  totalCount: number;
}

export type GetPendingSponsorshipRequestsErrorCode = 'REPOSITORY_ERROR';

export class GetPendingSponsorshipRequestsUseCase {
  constructor(
    private readonly sponsorshipRequestRepo: ISponsorshipRequestRepository,
    private readonly sponsorRepo: ISponsorRepository,
    private readonly output: UseCaseOutputPort<GetPendingSponsorshipRequestsResult>,
  ) {}

  async execute(
    input: GetPendingSponsorshipRequestsInput,
  ): Promise<
    Result<void, ApplicationErrorCode<GetPendingSponsorshipRequestsErrorCode, { message: string }>>
  > {
    try {
      const requests = await this.sponsorshipRequestRepo.findPendingByEntity(
        input.entityType,
        input.entityId,
      );

      const summaries: PendingSponsorshipRequestSummary[] = [];

      for (const request of requests) {
        const sponsor = await this.sponsorRepo.findById(request.sponsorId);

        const offeredAmount = Money.create(
          request.offeredAmount.amount,
          request.offeredAmount.currency,
        );
        const platformFee = request.getPlatformFee();
        const netAmount = request.getNetAmount();

        summaries.push({
          request,
          sponsor: sponsor ?? null,
          financials: {
            offeredAmount,
            platformFee,
            netAmount,
          },
        });
      }

      // Sort by creation date (newest first)
      summaries.sort((a, b) => b.request.createdAt.getTime() - a.request.createdAt.getTime());

      const result: GetPendingSponsorshipRequestsResult = {
        entityType: input.entityType,
        entityId: input.entityId,
        requests: summaries,
        totalCount: summaries.length,
      };

      this.output.present(result);

      return Result.ok(undefined);
    } catch (error) {
      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: {
          message:
            error instanceof Error
              ? error.message
              : 'Failed to fetch pending sponsorship requests',
        },
      });
    }
  }
}
