import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, Query } from '@nestjs/common';
import { PaymentsService } from '../services/payments.service';
import {
  ApiTags,
  ApiOperation,
  ApiNotFoundResponse,
  ApiBody,
  ApiParam,
  ApiBearerAuth,
  ApiHeader,
} from '@nestjs/swagger';
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
import { PaymentMethodService } from '../services/payment-method.service';
import { CreatePaymentMethodDto } from '../dto/create-payment-method.dto';
import { UpdatePaymentMethodDto } from '../dto/update-payment-method.dto';
import { VerifyPaymentDto } from '../dto/verify-payment.dto';
import { PaymentChartDto } from '../dto/payment-chart.dto';
import { RestId, UserId } from 'src/common/decorators';
import { AuthGuard } from 'src/modules/auth/guards/auth.guard';
import { API_HEADER_SLUG } from 'src/common/constants';
import { Permissions } from 'src/common/decorators/permissions.decorator';
import { Permission } from 'src/common/enums/permission.enum';

@ApiTags('payments')
@Controller()
export class PaymentsController {
  constructor(
    private readonly paymentsService: PaymentsService,
    private readonly paymentMethodService: PaymentMethodService,
  ) { }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Get('public/payments/methods/restaurant')
  @ApiOperation({ summary: 'Get the restaurant payment methods' })
  @ApiHeader(API_HEADER_SLUG)
  @ApiNotFoundResponse({ description: 'Restaurant payment methods not found' })
  getTheRestaurantPaymentMethods(@RestId() restId: string) {
    return this.paymentMethodService.findByRestaurant(restId);
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Get('public/payments')
  @ApiOperation({ summary: 'Get all the restaurant payments for user' })
  @ApiHeader(API_HEADER_SLUG)
  findAllByRestaurant(@UserId() userId: string, @RestId() restId: string) {
    return this.paymentsService.findAllPaymentsByRestaurantId(restId, userId);
  }

  @UseGuards(AuthGuard)
  @ApiBearerAuth()
  @Get('public/payments/pay-order/:orderId')
  @ApiOperation({ summary: 'Pay for an order' })
  @ApiParam({ name: 'orderId', type: 'string', description: 'Order ID' })
  @ApiHeader(API_HEADER_SLUG)
  payAnOrder(@Param('orderId') orderId: string) {
    return this.paymentsService.payOrder(orderId);
  }

  @Post('public/payments/verify')
  @ApiOperation({ summary: 'Verify a payment' })
  @ApiHeader(API_HEADER_SLUG)
  @ApiBody({ type: VerifyPaymentDto })
  @ApiNotFoundResponse({ description: 'Payment not found' })
  verifyPayment(@Body() verifyPaymentDto: VerifyPaymentDto) {
    return this.paymentsService.verifyOnlinePayment(verifyPaymentDto.authority, verifyPaymentDto.orderId);
  }

  /** admin routes */
  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Get('admin/payments/methods')
  @ApiOperation({ summary: 'Get restaurant all payment methods' })
  findByRestaurant(@RestId() restId: string) {
    return this.paymentMethodService.findByRestaurant(restId);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Post('admin/payments/methods')
  @ApiOperation({ summary: 'Create a new restaurant payment method' })
  @ApiBody({ type: CreatePaymentMethodDto })
  createRestaurantPaymentMethod(@RestId() restId: string, @Body() createPaymentMethodDto: CreatePaymentMethodDto) {
    return this.paymentMethodService.create(restId, createPaymentMethodDto);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Get('admin/payments/methods/:paymentMethodId')
  @ApiOperation({ summary: 'Get restaurant payment method by ID' })
  @ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
  findOneRestaurantPaymentMethod(@Param('paymentMethodId') paymentMethodId: string) {
    return this.paymentMethodService.findOneOrFail(paymentMethodId);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Patch('admin/payments/methods/:paymentMethodId')
  @ApiOperation({ summary: 'Update a restaurant payment method' })
  @ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
  @ApiBody({ type: UpdatePaymentMethodDto })
  updateRestaurantPaymentMethod(
    @Param('paymentMethodId') paymentMethodId: string,
    @Body() updatePaymentMethodDto: UpdatePaymentMethodDto,
  ) {
    return this.paymentMethodService.update(paymentMethodId, updatePaymentMethodDto);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Delete('admin/payments/methods/:paymentMethodId')
  @ApiOperation({ summary: 'Delete a restaurant payment method' })
  @ApiParam({ name: 'paymentMethodId', type: 'string', description: 'Payment method ID' })
  removeRestaurantPaymentMethod(@Param('paymentMethodId') paymentMethodId: string) {
    return this.paymentMethodService.remove(paymentMethodId);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.MANAGE_PAYMENTS)
  @ApiBearerAuth()
  @Post('admin/payments/verify-cash-method/:paymentId')
  @ApiOperation({ summary: 'Verify cash payment ' })
  @ApiParam({ name: 'paymentId', type: 'string', description: 'Payment ID' })
  verifyCashPayment(@Param('paymentId') paymentId: string) {
    return this.paymentsService.verifyCashPayment(paymentId);
  }

  @UseGuards(AdminAuthGuard)
  @Permissions(Permission.VIEW_REPORTS)
  @ApiBearerAuth()
  @Get('admin/payments/chart')
  @ApiOperation({ summary: 'Get payment chart data with date and period filters' })
  @ApiHeader(API_HEADER_SLUG)
  getPaymentChart(@Query() query: PaymentChartDto, @RestId() restId: string) {
    return this.paymentsService.getChartData(query, restId);
  }
}
