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, CurrentUser, Roles, JwtAuthGuard, RolesGuard } from '@modules/auth';
import { AdjustSubscriptionCommand } from '../../application/commands/adjust-subscription/adjust-subscription.command';
import { type AdjustSubscriptionResult } from '../../application/commands/adjust-subscription/adjust-subscription.handler';
import { BanUserCommand } from '../../application/commands/ban-user/ban-user.command';
import { type BanUserResult } from '../../application/commands/ban-user/ban-user.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 { GetAuditLogsQuery } from '../../application/queries/get-audit-logs/get-audit-logs.query';
import { GetDashboardStatsQuery } from '../../application/queries/get-dashboard-stats/get-dashboard-stats.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 DashboardStats,
  type RevenueStatsItem,
  type UserListResult,
  type UserDetail,
} from '../../domain/repositories/admin-query.repository';
import { type AuditLogListResult } from '../../domain/repositories/audit-log.repository';
import { type AdjustSubscriptionDto } from '../dto/adjust-subscription.dto';
import { type BanUserDto } from '../dto/ban-user.dto';
import { type GetAuditLogsQueryDto } from '../dto/get-audit-logs-query.dto';
import { type GetUsersQueryDto } from '../dto/get-users-query.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,
  ) {}

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

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

  // ── Audit Logs ──

  @Get('audit-logs')
  @ApiOperation({ summary: 'Get admin audit logs' })
  @ApiResponse({ status: 200, description: 'Audit logs retrieved successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized – missing or invalid JWT' })
  @ApiResponse({ status: 403, description: 'Forbidden – requires ADMIN role' })
  async getAuditLogs(
    @Query() query: GetAuditLogsQueryDto,
  ): Promise<AuditLogListResult> {
    return this.queryBus.execute(
      new GetAuditLogsQuery(
        query.page ?? 1,
        query.limit ?? 20,
        query.action,
        query.actorId,
        query.targetId,
        query.targetType,
        query.startDate ? new Date(query.startDate) : undefined,
        query.endDate ? new Date(query.endDate) : undefined,
      ),
    );
  }
}
