import {
  Body,
  Controller,
  Get,
  Param,
  Post,
  UseGuards,
} from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { type JwtPayload, CurrentUser, Roles, JwtAuthGuard, RolesGuard } from '@modules/auth';
import { CancelOrderCommand } from '../../application/commands/cancel-order/cancel-order.command';
import { type CancelOrderResult } from '../../application/commands/cancel-order/cancel-order.handler';
import { CreateOrderCommand } from '../../application/commands/create-order/create-order.command';
import { type CreateOrderResult } from '../../application/commands/create-order/create-order.handler';
import { HoldEscrowCommand } from '../../application/commands/hold-escrow/hold-escrow.command';
import { type HoldEscrowResult } from '../../application/commands/hold-escrow/hold-escrow.handler';
import { ReleaseEscrowCommand } from '../../application/commands/release-escrow/release-escrow.command';
import { type ReleaseEscrowResult } from '../../application/commands/release-escrow/release-escrow.handler';
import { type OrderStatusDto } from '../../application/queries/get-order-status/get-order-status.handler';
import { GetOrderStatusQuery } from '../../application/queries/get-order-status/get-order-status.query';
import { CancelOrderDto } from '../dto/cancel-order.dto';
import { CreateOrderDto } from '../dto/create-order.dto';

@ApiTags('orders')
@Controller('orders')
export class OrdersController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Create a new order from auction' })
  @ApiResponse({ status: 201, description: 'Order created successfully' })
  @ApiResponse({ status: 400, description: 'Bad request' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 409, description: 'Duplicate order (idempotency)' })
  @UseGuards(JwtAuthGuard)
  @Post()
  async createOrder(
    @Body() dto: CreateOrderDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<CreateOrderResult> {
    return this.commandBus.execute(
      new CreateOrderCommand(
        user.sub,
        dto.sellerId,
        dto.listingId,
        BigInt(dto.amountVND),
        dto.idempotencyKey,
      ),
    );
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Get order status by ID' })
  @ApiResponse({ status: 200, description: 'Order status retrieved' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Order not found' })
  @UseGuards(JwtAuthGuard)
  @Get(':id')
  async getOrderStatus(
    @Param('id') id: string,
    @CurrentUser() user: JwtPayload,
  ): Promise<OrderStatusDto> {
    return this.queryBus.execute(new GetOrderStatusQuery(id, user.sub));
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Cancel an order' })
  @ApiResponse({ status: 201, description: 'Order cancelled successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Order not found' })
  @ApiResponse({ status: 409, description: 'Invalid status transition' })
  @UseGuards(JwtAuthGuard)
  @Post(':id/cancel')
  async cancelOrder(
    @Param('id') id: string,
    @Body() dto: CancelOrderDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<CancelOrderResult> {
    return this.commandBus.execute(
      new CancelOrderCommand(id, user.sub, dto.reason),
    );
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Hold escrow funds for an order (admin only)' })
  @ApiResponse({ status: 201, description: 'Escrow held successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden — admin role required' })
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles('ADMIN')
  @Post(':id/escrow/hold')
  async holdEscrow(@Param('id') orderId: string): Promise<HoldEscrowResult> {
    return this.commandBus.execute(new HoldEscrowCommand(orderId));
  }

  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: 'Release escrow funds for an order (admin only)' })
  @ApiResponse({ status: 201, description: 'Escrow released successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden — admin role required' })
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles('ADMIN')
  @Post(':id/escrow/release')
  async releaseEscrow(@Param('id') orderId: string): Promise<ReleaseEscrowResult> {
    return this.commandBus.execute(new ReleaseEscrowCommand(orderId));
  }
}
