import {
  Body,
  Controller,
  Get,
  Ip,
  Param,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiParam, ApiQuery } from '@nestjs/swagger';
import { type JwtPayload, CurrentUser, Roles, JwtAuthGuard, RolesGuard } from '@modules/auth';
import {
  AdminFeatureListingCommand,
  type AdminFeatureListingResult,
} from '@modules/listings';
import { ApproveKycCommand } from '../../application/commands/approve-kyc/approve-kyc.command';
import { type ApproveKycResult } from '../../application/commands/approve-kyc/approve-kyc.handler';
import { ApproveListingCommand } from '../../application/commands/approve-listing/approve-listing.command';
import { type ApproveListingResult } from '../../application/commands/approve-listing/approve-listing.handler';
import { BulkModerateListingsCommand } from '../../application/commands/bulk-moderate-listings/bulk-moderate-listings.command';
import { type BulkModerateResult } from '../../application/commands/bulk-moderate-listings/bulk-moderate-listings.handler';
import { RejectKycCommand } from '../../application/commands/reject-kyc/reject-kyc.command';
import { type RejectKycResult } from '../../application/commands/reject-kyc/reject-kyc.handler';
import { RejectListingCommand } from '../../application/commands/reject-listing/reject-listing.command';
import { type RejectListingResult } from '../../application/commands/reject-listing/reject-listing.handler';
import { GetKycQueueQuery } from '../../application/queries/get-kyc-queue/get-kyc-queue.query';
import { GetModerationQueueQuery } from '../../application/queries/get-moderation-queue/get-moderation-queue.query';
import {
  type ModerationQueueResult,
  type KycQueueResult,
} from '../../domain/repositories/admin-query.repository';
import { AdminFeatureListingDto } from '../dto/admin-feature-listing.dto';
import { ApproveKycDto } from '../dto/approve-kyc.dto';
import { ApproveListingDto } from '../dto/approve-listing.dto';
import { BulkModerateDto } from '../dto/bulk-moderate.dto';
import { RejectKycDto } from '../dto/reject-kyc.dto';
import { RejectListingDto } from '../dto/reject-listing.dto';
import { GetFlaggedListingsQuery } from '../../application/queries/get-flagged-listings/get-flagged-listings.query';
import type { FlaggedListingsResult } from '../../application/queries/get-flagged-listings/get-flagged-listings.handler';

@ApiTags('admin')
@ApiBearerAuth('JWT')
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ADMIN')
export class AdminModerationController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  // ── Moderation ──

  @Get('moderation')
  @ApiOperation({ summary: 'Get listing moderation queue' })
  @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default 1)' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default 20)' })
  @ApiResponse({ status: 200, description: 'Moderation queue retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getModerationQueue(
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ): Promise<ModerationQueueResult> {
    return this.queryBus.execute(
      new GetModerationQueueQuery(
        page ? parseInt(page, 10) : 1,
        limit ? parseInt(limit, 10) : 20,
      ),
    );
  }

  @Post('moderation/approve')
  @ApiOperation({ summary: 'Approve a listing' })
  @ApiResponse({ status: 201, description: 'Listing approved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async approveListing(
    @Body() dto: ApproveListingDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<ApproveListingResult> {
    return this.commandBus.execute(
      new ApproveListingCommand(dto.listingId, user.sub, dto.moderationNotes),
    );
  }

  @Post('moderation/reject')
  @ApiOperation({ summary: 'Reject a listing' })
  @ApiResponse({ status: 201, description: 'Listing rejected successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async rejectListing(
    @Body() dto: RejectListingDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<RejectListingResult> {
    return this.commandBus.execute(
      new RejectListingCommand(dto.listingId, user.sub, dto.reason),
    );
  }

  @Post('moderation/bulk')
  @ApiOperation({ summary: 'Bulk approve or reject listings' })
  @ApiResponse({ status: 201, description: 'Bulk moderation completed successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async bulkModerate(
    @Body() dto: BulkModerateDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<BulkModerateResult> {
    return this.commandBus.execute(
      new BulkModerateListingsCommand(dto.listingIds, user.sub, dto.action, dto.reason),
    );
  }

  @Post('listings/:id/feature')
  @ApiOperation({
    summary: 'Admin: feature or unfeature a listing manually (audited, no payment)',
  })
  @ApiParam({ name: 'id', description: 'Listing UUID' })
  @ApiResponse({ status: 201, description: 'Listing featured state updated successfully' })
  @ApiResponse({ status: 400, description: 'Validation error' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async adminFeatureListing(
    @Param('id') id: string,
    @Body() dto: AdminFeatureListingDto,
    @CurrentUser() user: JwtPayload,
    @Ip() ip: string,
  ): Promise<AdminFeatureListingResult> {
    return this.commandBus.execute(
      new AdminFeatureListingCommand(
        id,
        user.sub,
        dto.action,
        dto.durationDays ?? null,
        dto.reason,
        ip ?? null,
      ),
    );
  }

  // ── Flagged Listings (User Reports) ──

  @Get('flagged-listings')
  @ApiOperation({ summary: 'Get listings flagged by users (báo cáo)' })
  @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default 1)' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default 20)' })
  @ApiResponse({ status: 200, description: 'Flagged listings queue retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getFlaggedListings(
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ): Promise<FlaggedListingsResult> {
    return this.queryBus.execute(
      new GetFlaggedListingsQuery(
        page ? parseInt(page, 10) : 1,
        limit ? parseInt(limit, 10) : 20,
      ),
    );
  }

  // ── KYC ──

  @Get('kyc')
  @ApiOperation({ summary: 'Get KYC verification queue' })
  @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default 1)' })
  @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default 20)' })
  @ApiResponse({ status: 200, description: 'KYC queue retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getKycQueue(
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ): Promise<KycQueueResult> {
    return this.queryBus.execute(
      new GetKycQueueQuery(
        page ? parseInt(page, 10) : 1,
        limit ? parseInt(limit, 10) : 20,
      ),
    );
  }

  @Post('kyc/approve')
  @ApiOperation({ summary: 'Approve KYC verification' })
  @ApiResponse({ status: 201, description: 'KYC approved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async approveKyc(
    @Body() dto: ApproveKycDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<ApproveKycResult> {
    return this.commandBus.execute(
      new ApproveKycCommand(dto.userId, user.sub, dto.comments),
    );
  }

  @Post('kyc/reject')
  @ApiOperation({ summary: 'Reject KYC verification' })
  @ApiResponse({ status: 201, description: 'KYC rejected successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async rejectKyc(
    @Body() dto: RejectKycDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<RejectKycResult> {
    return this.commandBus.execute(
      new RejectKycCommand(dto.userId, user.sub, dto.reason),
    );
  }
}
