import {
  Controller,
  Get,
  Post,
  Patch,
  Body,
  Param,
  Query,
  UseGuards,
  Logger,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiQuery,
  ApiBody,
} from '@nestjs/swagger';
import { AuthGuard } from '@nestjs/passport';
import { AdminService } from './admin.service';
import { Roles } from '../../common/decorators/roles.decorator';
import { RolesGuard } from '../../common/guards/roles.guard';
import { UserRole } from '../../common/enums';

@ApiTags('Admin')
@Controller('admin')
@ApiBearerAuth('BearerAuth')
@UseGuards(AuthGuard('jwt'), RolesGuard)
@Roles(UserRole.ADMIN)
export class AdminController {
  private readonly logger = new Logger(AdminController.name);

  constructor(private readonly adminService: AdminService) {}

  @Get('stats')
  @ApiOperation({
    summary: 'Get platform statistics',
    description:
      'Get overall platform statistics including request counts, user counts, and transaction data',
  })
  @ApiResponse({ status: 200, description: 'Platform statistics' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden - Admin only' })
  async getStats() {
    this.logger.debug('Fetching platform stats');
    return this.adminService.getPlatformStats();
  }

  @Get('health')
  @ApiOperation({
    summary: 'Get system health',
    description:
      'Get health status of all platform services (database, blockchain, storage, queue)',
  })
  @ApiResponse({ status: 200, description: 'System health status' })
  async getHealth() {
    return this.adminService.getSystemHealth();
  }

  @Get('activity')
  @ApiOperation({
    summary: 'Get recent activity',
    description: 'Get recent audit log entries for platform activity monitoring',
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    type: Number,
    description: 'Number of recent entries (default: 20)',
  })
  @ApiResponse({ status: 200, description: 'Recent activity logs' })
  async getRecentActivity(@Query('limit') limit?: number) {
    return this.adminService.getRecentActivity(limit || 20);
  }

  @Get('blockchain/blocks')
  @ApiOperation({
    summary: 'Get recent blockchain blocks',
    description: 'Get the most recent blocks from the blockchain',
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    type: Number,
    description: 'Number of blocks to fetch (default: 5)',
  })
  @ApiResponse({ status: 200, description: 'Recent blockchain blocks' })
  async getBlockchainBlocks(@Query('limit') limit?: number) {
    return this.adminService.getBlockchainBlocks(limit || 5);
  }

  @Get('blockchain/transactions')
  @ApiOperation({
    summary: 'List blockchain transactions',
    description: 'Get paginated list of blockchain transactions with optional status filter',
  })
  @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)',
  })
  @ApiQuery({
    name: 'status',
    required: false,
    description: 'Filter by transaction status (PENDING, CONFIRMED, FAILED)',
  })
  @ApiResponse({ status: 200, description: 'Paginated blockchain transactions' })
  async getBlockchainTransactions(
    @Query('page') page?: number,
    @Query('limit') limit?: number,
    @Query('status') status?: string,
  ) {
    return this.adminService.getBlockchainTransactions(page || 1, limit || 20, status);
  }

  @Post('departments')
  @ApiOperation({
    summary: 'Onboard new department',
    description: 'Create a new department with wallet and API key generation',
  })
  @ApiBody({
    schema: {
      type: 'object',
      required: ['code', 'name', 'contactEmail'],
      properties: {
        code: { type: 'string', example: 'POLICE_DEPT' },
        name: { type: 'string', example: 'Police Department' },
        description: { type: 'string', example: 'Law enforcement department' },
        contactEmail: { type: 'string', example: 'police@goa.gov.in' },
        contactPhone: { type: 'string', example: '+91-832-6666666' },
      },
    },
  })
  @ApiResponse({ status: 201, description: 'Department onboarded successfully' })
  @ApiResponse({ status: 400, description: 'Invalid input' })
  @ApiResponse({ status: 409, description: 'Department already exists' })
  async onboardDepartment(@Body() dto: any) {
    return this.adminService.onboardDepartment(dto);
  }

  @Get('departments')
  @ApiOperation({
    summary: 'List all departments',
    description: 'Get list of all departments with pagination',
  })
  @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: 'List of departments' })
  async getDepartments(@Query('page') page?: number, @Query('limit') limit?: number) {
    return this.adminService.getDepartments(page || 1, limit || 20);
  }

  @Get('departments/:id')
  @ApiOperation({
    summary: 'Get department details',
    description: 'Get detailed information about a specific department',
  })
  @ApiResponse({ status: 200, description: 'Department details' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  async getDepartment(@Param('id') id: string) {
    return this.adminService.getDepartment(id);
  }

  @Patch('departments/:id')
  @ApiOperation({
    summary: 'Update department',
    description: 'Update department information',
  })
  @ApiResponse({ status: 200, description: 'Department updated' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  async updateDepartment(@Param('id') id: string, @Body() dto: any) {
    return this.adminService.updateDepartment(id, dto);
  }

  @Post('departments/:id/regenerate-api-key')
  @ApiOperation({
    summary: 'Regenerate department API key',
    description: 'Generate a new API key for the department',
  })
  @ApiResponse({ status: 200, description: 'API key regenerated' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  async regenerateApiKey(@Param('id') id: string) {
    return this.adminService.regenerateDepartmentApiKey(id);
  }

  @Patch('departments/:id/deactivate')
  @ApiOperation({
    summary: 'Deactivate department',
    description: 'Deactivate a department',
  })
  @ApiResponse({ status: 200, description: 'Department deactivated' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  async deactivateDepartment(@Param('id') id: string) {
    return this.adminService.deactivateDepartment(id);
  }

  @Patch('departments/:id/activate')
  @ApiOperation({
    summary: 'Activate department',
    description: 'Activate a department',
  })
  @ApiResponse({ status: 200, description: 'Department activated' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  async activateDepartment(@Param('id') id: string) {
    return this.adminService.activateDepartment(id);
  }

  @Get('users')
  @ApiOperation({
    summary: 'List all users',
    description: 'Get list of all users with pagination',
  })
  @ApiResponse({ status: 200, description: 'List of users' })
  async getUsers() {
    return this.adminService.getUsers();
  }

  @Get('blockchain/events')
  @ApiOperation({
    summary: 'List blockchain events',
    description: 'Get paginated list of blockchain events with optional filters',
  })
  @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)',
  })
  @ApiQuery({ name: 'eventType', required: false, description: 'Filter by event type' })
  @ApiQuery({ name: 'contractAddress', required: false, description: 'Filter by contract address' })
  @ApiResponse({ status: 200, description: 'Paginated blockchain events' })
  async getBlockchainEvents(
    @Query('page') page?: number,
    @Query('limit') limit?: number,
    @Query('eventType') eventType?: string,
    @Query('contractAddress') contractAddress?: string,
  ) {
    return this.adminService.getBlockchainEvents(
      page || 1,
      limit || 20,
      eventType,
      contractAddress,
    );
  }

  @Get('logs')
  @ApiOperation({
    summary: 'List application logs',
    description: 'Get paginated list of application logs with optional filters',
  })
  @ApiQuery({
    name: 'page',
    required: false,
    type: Number,
    description: 'Page number (default: 1)',
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    type: Number,
    description: 'Items per page (default: 50)',
  })
  @ApiQuery({
    name: 'level',
    required: false,
    description: 'Filter by log level (INFO, WARN, ERROR)',
  })
  @ApiQuery({ name: 'module', required: false, description: 'Filter by module name' })
  @ApiQuery({ name: 'search', required: false, description: 'Search in log messages' })
  @ApiResponse({ status: 200, description: 'Paginated application logs' })
  async getApplicationLogs(
    @Query('page') page?: number,
    @Query('limit') limit?: number,
    @Query('level') level?: string,
    @Query('module') module?: string,
    @Query('search') search?: string,
  ) {
    return this.adminService.getApplicationLogs(page || 1, limit || 50, level, module, search);
  }

  @Get('documents/:requestId')
  @ApiOperation({
    summary: 'Get documents for a request',
    description: 'Get all documents with versions and department reviews for a specific request',
  })
  @ApiResponse({ status: 200, description: 'Documents with version history and reviews' })
  async getRequestDocuments(@Param('requestId') requestId: string) {
    return this.adminService.getRequestDocuments(requestId);
  }
}
