import { Controller, Get, Post, Patch, Delete, Body, Query, HttpCode, HttpStatus, Inject } from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
import { RequireAuthenticatedUser } from '../auth/RequireAuthenticatedUser';
import { RequireRoles } from '../auth/RequireRoles';
import { RequireCapability } from '../policy/RequireCapability';
import { PaymentsService } from './PaymentsService';
import { CreatePaymentInput, CreatePaymentOutput, UpdatePaymentStatusInput, UpdatePaymentStatusOutput, GetPaymentsQuery, GetPaymentsOutput, GetMembershipFeesQuery, GetMembershipFeesOutput, UpsertMembershipFeeInput, UpsertMembershipFeeOutput, UpdateMemberPaymentInput, UpdateMemberPaymentOutput, GetPrizesQuery, GetPrizesOutput, CreatePrizeInput, CreatePrizeOutput, AwardPrizeInput, AwardPrizeOutput, DeletePrizeInput, DeletePrizeOutput, GetWalletQuery, GetWalletOutput, ProcessWalletTransactionInput, ProcessWalletTransactionOutput } from './dtos/PaymentsDto';

@ApiTags('payments')
@RequireAuthenticatedUser()
@RequireRoles('admin')
@Controller('payments')
export class PaymentsController {
  constructor(@Inject(PaymentsService) private readonly paymentsService: PaymentsService) {}

  @Get()
  @RequireCapability('payments.admin', 'view')
  @ApiOperation({ summary: 'Get payments based on filters' })
  @ApiResponse({ status: 200, description: 'List of payments', type: GetPaymentsOutput })
  async getPayments(@Query() query: GetPaymentsQuery): Promise<GetPaymentsOutput> {
    return this.paymentsService.getPayments(query);
  }

  @Post()
  @RequireCapability('payments.admin', 'mutate')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new payment' })
  @ApiResponse({ status: 201, description: 'Payment created', type: CreatePaymentOutput })
  async createPayment(@Body() input: CreatePaymentInput): Promise<CreatePaymentOutput> {
    return this.paymentsService.createPayment(input);
  }

  @Patch('status')
  @RequireCapability('payments.admin', 'mutate')
  @ApiOperation({ summary: 'Update the status of a payment' })
  @ApiResponse({ status: 200, description: 'Payment status updated', type: UpdatePaymentStatusOutput })
  async updatePaymentStatus(@Body() input: UpdatePaymentStatusInput): Promise<UpdatePaymentStatusOutput> {
    return this.paymentsService.updatePaymentStatus(input);
  }

  @Get('membership-fees')
  @RequireCapability('payments.admin', 'view')
  @ApiOperation({ summary: 'Get membership fees and member payments' })
  @ApiResponse({ status: 200, description: 'Membership fee configuration and member payments', type: GetMembershipFeesOutput })
  async getMembershipFees(@Query() query: GetMembershipFeesQuery): Promise<GetMembershipFeesOutput> {
    return this.paymentsService.getMembershipFees(query);
  }

  @Post('membership-fees')
  @RequireCapability('payments.admin', 'mutate')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create or update membership fee configuration' })
  @ApiResponse({ status: 201, description: 'Membership fee configuration created or updated', type: UpsertMembershipFeeOutput })
  async upsertMembershipFee(@Body() input: UpsertMembershipFeeInput): Promise<UpsertMembershipFeeOutput> {
    return this.paymentsService.upsertMembershipFee(input);
  }

  @Patch('membership-fees/member-payment')
  @RequireCapability('payments.admin', 'mutate')
  @ApiOperation({ summary: 'Record or update a member payment' })
  @ApiResponse({ status: 200, description: 'Member payment recorded or updated', type: UpdateMemberPaymentOutput })
  async updateMemberPayment(@Body() input: UpdateMemberPaymentInput): Promise<UpdateMemberPaymentOutput> {
    return this.paymentsService.updateMemberPayment(input);
  }
  @Get('prizes')
  @RequireCapability('payments.admin', 'view')
  @ApiOperation({ summary: 'Get prizes for a league or season' })
  @ApiResponse({ status: 200, description: 'List of prizes', type: GetPrizesOutput })
  async getPrizes(@Query() query: GetPrizesQuery): Promise<GetPrizesOutput> {
    return this.paymentsService.getPrizes(query);
  }

  @Post('prizes')
  @RequireCapability('payments.admin', 'mutate')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new prize' })
  @ApiResponse({ status: 201, description: 'Prize created', type: CreatePrizeOutput })
  async createPrize(@Body() input: CreatePrizeInput): Promise<CreatePrizeOutput> {
    return this.paymentsService.createPrize(input);
  }

  @Patch('prizes/award')
  @RequireCapability('payments.admin', 'mutate')
  @ApiOperation({ summary: 'Award a prize to a driver' })
  @ApiResponse({ status: 200, description: 'Prize awarded', type: AwardPrizeOutput })
  async awardPrize(@Body() input: AwardPrizeInput): Promise<AwardPrizeOutput> {
    return this.paymentsService.awardPrize(input);
  }

  @Delete('prizes')
  @RequireCapability('payments.admin', 'mutate')
  @ApiOperation({ summary: 'Delete a prize' })
  @ApiResponse({ status: 200, description: 'Prize deleted', type: DeletePrizeOutput })
  async deletePrize(@Query() query: DeletePrizeInput): Promise<DeletePrizeOutput> {
    return this.paymentsService.deletePrize(query);
  }
  @Get('wallets')
  @RequireCapability('payments.admin', 'view')
  @ApiOperation({ summary: 'Get wallet information and transactions' })
  @ApiResponse({ status: 200, description: 'Wallet and transaction data', type: GetWalletOutput })
  async getWallet(@Query() query: GetWalletQuery): Promise<GetWalletOutput> {
    return this.paymentsService.getWallet(query);
  }

  @Post('wallets/transactions')
  @RequireCapability('payments.admin', 'mutate')
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Process a wallet transaction (deposit or withdrawal)' })
  @ApiResponse({ status: 201, description: 'Wallet transaction processed', type: ProcessWalletTransactionOutput })
  async processWalletTransaction(@Body() input: ProcessWalletTransactionInput): Promise<ProcessWalletTransactionOutput> {
    return this.paymentsService.processWalletTransaction(input);
  }
}
