import {
  Body,
  Controller,
  Get,
  Param,
  Patch,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { type CommandBus, type QueryBus } from '@nestjs/cqrs';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery, ApiParam } from '@nestjs/swagger';
import { type JwtPayload } from '@modules/auth/infrastructure/services/token.service';
import { CurrentUser } from '@modules/auth/presentation/decorators/current-user.decorator';
import { Roles } from '@modules/auth/presentation/decorators/roles.decorator';
import { JwtAuthGuard } from '@modules/auth/presentation/guards/jwt-auth.guard';
import { RolesGuard } from '@modules/auth/presentation/guards/roles.guard';
import { AdjustSubscriptionCommand } from '../../application/commands/adjust-subscription/adjust-subscription.command';
import { type AdjustSubscriptionResult } from '../../application/commands/adjust-subscription/adjust-subscription.handler';
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 { BanUserCommand } from '../../application/commands/ban-user/ban-user.command';
import { type BanUserResult } from '../../application/commands/ban-user/ban-user.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 { UpdateUserStatusCommand } from '../../application/commands/update-user-status/update-user-status.command';
import { type UpdateUserStatusResult } from '../../application/commands/update-user-status/update-user-status.handler';
import { GetDashboardStatsQuery } from '../../application/queries/get-dashboard-stats/get-dashboard-stats.query';
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 { GetRevenueStatsQuery } from '../../application/queries/get-revenue-stats/get-revenue-stats.query';
import { GetUserDetailQuery } from '../../application/queries/get-user-detail/get-user-detail.query';
import { GetUsersQuery } from '../../application/queries/get-users/get-users.query';
import {
  type ModerationQueueResult,
  type DashboardStats,
  type RevenueStatsItem,
  type UserListResult,
  type UserDetail,
  type KycQueueResult,
} from '../../domain/repositories/admin-query.repository';
import { type AdjustSubscriptionDto } from '../dto/adjust-subscription.dto';
import { type ApproveKycDto } from '../dto/approve-kyc.dto';
import { type ApproveListingDto } from '../dto/approve-listing.dto';
import { type BanUserDto } from '../dto/ban-user.dto';
import { type BulkModerateDto } from '../dto/bulk-moderate.dto';
import { type GetUsersQueryDto } from '../dto/get-users-query.dto';
import { type RejectKycDto } from '../dto/reject-kyc.dto';
import { type RejectListingDto } from '../dto/reject-listing.dto';
import { type RevenueStatsDto } from '../dto/revenue-stats.dto';
import { type UpdateUserStatusDto } from '../dto/update-user-status.dto';

@ApiTags('admin')
@ApiBearerAuth('JWT')
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('ADMIN')
export class AdminController {
  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),
    );
  }

  // ── User Management ──

  @Get('users')
  @ApiOperation({ summary: 'List users with optional filters' })
  @ApiResponse({ status: 200, description: 'User list retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getUsers(
    @Query() query: GetUsersQueryDto,
  ): Promise<UserListResult> {
    return this.queryBus.execute(
      new GetUsersQuery(
        query.page ?? 1,
        query.limit ?? 20,
        query.role,
        query.isActive,
        query.search,
      ),
    );
  }

  @Get('users/:id')
  @ApiOperation({ summary: 'Get user details by ID' })
  @ApiParam({ name: 'id', description: 'User ID' })
  @ApiResponse({ status: 200, description: 'User detail retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getUserDetail(
    @Param('id') id: string,
  ): Promise<UserDetail> {
    return this.queryBus.execute(new GetUserDetailQuery(id));
  }

  @Patch('users/status')
  @ApiOperation({ summary: 'Update user active status' })
  @ApiResponse({ status: 200, description: 'User status updated successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async updateUserStatus(
    @Body() dto: UpdateUserStatusDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<UpdateUserStatusResult> {
    return this.commandBus.execute(
      new UpdateUserStatusCommand(dto.userId, user.sub, dto.isActive, dto.reason),
    );
  }

  @Post('users/ban')
  @ApiOperation({ summary: 'Ban or unban a user' })
  @ApiResponse({ status: 201, description: 'User ban status updated successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async banUser(
    @Body() dto: BanUserDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<BanUserResult> {
    return this.commandBus.execute(
      new BanUserCommand(dto.userId, user.sub, dto.reason, dto.unban ?? false),
    );
  }

  // ── 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),
    );
  }

  // ── Subscription Management ──

  @Post('subscriptions/adjust')
  @ApiOperation({ summary: 'Adjust user subscription plan' })
  @ApiResponse({ status: 201, description: 'Subscription adjusted successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async adjustSubscription(
    @Body() dto: AdjustSubscriptionDto,
    @CurrentUser() user: JwtPayload,
  ): Promise<AdjustSubscriptionResult> {
    return this.commandBus.execute(
      new AdjustSubscriptionCommand(dto.userId, user.sub, dto.newPlanTier, dto.reason),
    );
  }

  // ── Dashboard ──

  @Get('dashboard')
  @ApiOperation({ summary: 'Get admin dashboard statistics' })
  @ApiResponse({ status: 200, description: 'Dashboard stats retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getDashboardStats(): Promise<DashboardStats> {
    return this.queryBus.execute(new GetDashboardStatsQuery());
  }

  @Get('revenue')
  @ApiOperation({ summary: 'Get revenue statistics' })
  @ApiQuery({ name: 'startDate', required: true, type: String, description: 'Start date (ISO 8601)' })
  @ApiQuery({ name: 'endDate', required: true, type: String, description: 'End date (ISO 8601)' })
  @ApiQuery({ name: 'groupBy', required: false, enum: ['day', 'month'], description: 'Group results by day or month (default month)' })
  @ApiResponse({ status: 200, description: 'Revenue stats retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getRevenueStats(
    @Query() dto: RevenueStatsDto,
  ): Promise<RevenueStatsItem[]> {
    return this.queryBus.execute(
      new GetRevenueStatsQuery(
        new Date(dto.startDate),
        new Date(dto.endDate),
        dto.groupBy ?? 'month',
      ),
    );
  }
}
