import { Controller, Get, Post, Put, Body, HttpCode, HttpStatus, Param, Query, Inject } from '@nestjs/common'; import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger'; import { Public } from '../auth/Public'; import { RequireAuthenticatedUser } from '../auth/RequireAuthenticatedUser'; import { RequireRoles } from '../auth/RequireRoles'; import { RequireCapability } from '../policy/RequireCapability'; import { SponsorService } from './SponsorService'; import { GetEntitySponsorshipPricingResultDTO } from './dtos/GetEntitySponsorshipPricingResultDTO'; import { GetSponsorsOutputDTO } from './dtos/GetSponsorsOutputDTO'; import { CreateSponsorInputDTO } from './dtos/CreateSponsorInputDTO'; import { CreateSponsorOutputDTO } from './dtos/CreateSponsorOutputDTO'; import { GetSponsorDashboardQueryParamsDTO } from './dtos/GetSponsorDashboardQueryParamsDTO'; import { SponsorDashboardDTO } from './dtos/SponsorDashboardDTO'; import { GetSponsorSponsorshipsQueryParamsDTO } from './dtos/GetSponsorSponsorshipsQueryParamsDTO'; import { SponsorSponsorshipsDTO } from './dtos/SponsorSponsorshipsDTO'; import { GetSponsorOutputDTO } from './dtos/GetSponsorOutputDTO'; import { GetPendingSponsorshipRequestsOutputDTO } from './dtos/GetPendingSponsorshipRequestsOutputDTO'; import { AcceptSponsorshipRequestInputDTO } from './dtos/AcceptSponsorshipRequestInputDTO'; import { RejectSponsorshipRequestInputDTO } from './dtos/RejectSponsorshipRequestInputDTO'; import { PaymentMethodDTO } from './dtos/PaymentMethodDTO'; import { InvoiceDTO } from './dtos/InvoiceDTO'; import { BillingStatsDTO } from './dtos/BillingStatsDTO'; import { AvailableLeagueDTO } from './dtos/AvailableLeagueDTO'; import { LeagueDetailDTO } from './dtos/LeagueDetailDTO'; import { SponsorDriverDTO } from './dtos/SponsorDriverDTO'; import { SponsorRaceDTO } from './dtos/RaceDTO'; import { SponsorProfileDTO } from './dtos/SponsorProfileDTO'; import { NotificationSettingsDTO } from './dtos/NotificationSettingsDTO'; import { PrivacySettingsDTO } from './dtos/PrivacySettingsDTO'; import type { AcceptSponsorshipRequestResultViewModel } from './presenters/AcceptSponsorshipRequestPresenter'; import type { RejectSponsorshipRequestResult } from '@core/racing/application/use-cases/RejectSponsorshipRequestUseCase'; @ApiTags('sponsors') @Controller('sponsors') export class SponsorController { constructor(@Inject(SponsorService) private readonly sponsorService: SponsorService) {} @Public() @Get('pricing') @ApiOperation({ summary: 'Get sponsorship pricing for an entity' }) @ApiResponse({ status: 200, description: 'Sponsorship pricing', type: GetEntitySponsorshipPricingResultDTO, }) async getEntitySponsorshipPricing(): Promise { return await this.sponsorService.getEntitySponsorshipPricing(); } @Get() @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get all sponsors' }) @ApiResponse({ status: 200, description: 'List of sponsors', type: GetSponsorsOutputDTO, }) async getSponsors(): Promise { return await this.sponsorService.getSponsors(); } @Post() @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'mutate') @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: 'Create a new sponsor' }) @ApiResponse({ status: 201, description: 'Sponsor created', type: CreateSponsorOutputDTO, }) async createSponsor(@Body() input: CreateSponsorInputDTO): Promise { return await this.sponsorService.createSponsor(input); } @Get('dashboard/:sponsorId') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get sponsor dashboard metrics and sponsored leagues' }) @ApiResponse({ status: 200, description: 'Sponsor dashboard data', type: SponsorDashboardDTO, }) @ApiResponse({ status: 404, description: 'Sponsor not found' }) async getSponsorDashboard( @Param('sponsorId') sponsorId: string, ): Promise { return await this.sponsorService.getSponsorDashboard({ sponsorId, } as GetSponsorDashboardQueryParamsDTO); } @Get(':sponsorId/sponsorships') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get all sponsorships for a given sponsor', }) @ApiResponse({ status: 200, description: 'List of sponsorships', type: SponsorSponsorshipsDTO, }) @ApiResponse({ status: 404, description: 'Sponsor not found' }) async getSponsorSponsorships( @Param('sponsorId') sponsorId: string, ): Promise { return await this.sponsorService.getSponsorSponsorships({ sponsorId, } as GetSponsorSponsorshipsQueryParamsDTO); } @Get('requests') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get pending sponsorship requests' }) @ApiResponse({ status: 200, description: 'List of pending sponsorship requests', type: GetPendingSponsorshipRequestsOutputDTO, }) async getPendingSponsorshipRequests( @Query() query: { entityType: string; entityId: string }, ): Promise { return await this.sponsorService.getPendingSponsorshipRequests( query as { entityType: import('@core/racing/domain/entities/SponsorshipRequest').SponsorableEntityType; entityId: string; }, ); } @Get(':sponsorId') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get a sponsor by ID' }) @ApiResponse({ status: 200, description: 'Sponsor data', type: GetSponsorOutputDTO, }) @ApiResponse({ status: 404, description: 'Sponsor not found' }) async getSponsor(@Param('sponsorId') sponsorId: string): Promise { return await this.sponsorService.getSponsor(sponsorId); } @Post('requests/:requestId/accept') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'mutate') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Accept a sponsorship request' }) @ApiResponse({ status: 200, description: 'Sponsorship request accepted' }) @ApiResponse({ status: 400, description: 'Invalid request' }) @ApiResponse({ status: 404, description: 'Request not found' }) async acceptSponsorshipRequest( @Param('requestId') requestId: string, @Body() input: AcceptSponsorshipRequestInputDTO, ): Promise { return await this.sponsorService.acceptSponsorshipRequest( requestId, input.respondedBy, ); } @Post('requests/:requestId/reject') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'mutate') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Reject a sponsorship request' }) @ApiResponse({ status: 200, description: 'Sponsorship request rejected' }) @ApiResponse({ status: 400, description: 'Invalid request' }) @ApiResponse({ status: 404, description: 'Request not found' }) async rejectSponsorshipRequest( @Param('requestId') requestId: string, @Body() input: RejectSponsorshipRequestInputDTO, ): Promise { return await this.sponsorService.rejectSponsorshipRequest( requestId, input.respondedBy, input.reason, ); } @Get('billing/:sponsorId') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get sponsor billing information' }) @ApiResponse({ status: 200, description: 'Sponsor billing data', type: Object }) async getSponsorBilling( @Param('sponsorId') sponsorId: string, ): Promise<{ paymentMethods: PaymentMethodDTO[]; invoices: InvoiceDTO[]; stats: BillingStatsDTO; }> { return await this.sponsorService.getSponsorBilling(sponsorId); } @Get('leagues/available') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get available leagues for sponsorship' }) @ApiResponse({ status: 200, description: 'Available leagues', type: [AvailableLeagueDTO], }) async getAvailableLeagues(): Promise { const presenter = await this.sponsorService.getAvailableLeagues(); return presenter.viewModel; } @Get('leagues/:leagueId/detail') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get detailed league information for sponsors' }) @ApiResponse({ status: 200, description: 'League detail data', type: Object }) async getLeagueDetail( @Param('leagueId') leagueId: string, ): Promise<{ league: LeagueDetailDTO; drivers: SponsorDriverDTO[]; races: SponsorRaceDTO[]; } | null> { const presenter = await this.sponsorService.getLeagueDetail(leagueId); return presenter.viewModel; } @Get('settings/:sponsorId') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'view') @ApiOperation({ summary: 'Get sponsor settings' }) @ApiResponse({ status: 200, description: 'Sponsor settings', type: Object }) async getSponsorSettings( @Param('sponsorId') sponsorId: string, ): Promise<{ profile: SponsorProfileDTO; notifications: NotificationSettingsDTO; privacy: PrivacySettingsDTO; } | null> { const presenter = await this.sponsorService.getSponsorSettings(sponsorId); return presenter.viewModel; } @Put('settings/:sponsorId') @RequireAuthenticatedUser() @RequireRoles('admin') @RequireCapability('sponsors.portal', 'mutate') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Update sponsor settings' }) @ApiResponse({ status: 200, description: 'Settings updated successfully' }) async updateSponsorSettings( @Param('sponsorId') sponsorId: string, @Body() input: { profile?: Partial; notifications?: Partial; privacy?: Partial; }, ): Promise<{ success: boolean; errorCode?: string; message?: string } | null> { const presenter = await this.sponsorService.updateSponsorSettings(sponsorId, input); return presenter.viewModel; } }