import {
  Controller,
  Get,
  Query,
  Param,
  Headers,
  UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as jwt from 'jsonwebtoken';
import { UserService } from '../../application/services/user.service';
import { UserType } from '../../domain/entities/user.entity';

/**
 * Admin User Management Controller
 * Provides endpoints for admin dashboard user management
 */
@Controller('users/admin')
export class AdminUserController {
  private readonly jwtSecret: string;

  constructor(
    private readonly userService: UserService,
    private readonly configService: ConfigService,
  ) {
    this.jwtSecret =
      this.configService.get('JWT_SECRET') || 'iconsulting-secret-key';
  }

  /**
   * Verify admin JWT token
   */
  private verifyAdmin(authorization: string): { id: string; username: string } {
    if (!authorization?.startsWith('Bearer ')) {
      throw new UnauthorizedException('Missing authorization token');
    }

    const token = authorization.substring(7);

    try {
      const decoded = jwt.verify(token, this.jwtSecret) as {
        sub: string;
        username: string;
        role?: string;
      };

      return { id: decoded.sub, username: decoded.username };
    } catch {
      throw new UnauthorizedException('Invalid or expired token');
    }
  }

  /**
   * GET /users/admin/list
   * List users with pagination and filters
   */
  @Get('list')
  async listUsers(
    @Headers('authorization') auth: string,
    @Query('type') type?: UserType,
    @Query('phone') phone?: string,
    @Query('nickname') nickname?: string,
    @Query('page') page = '1',
    @Query('pageSize') pageSize = '20',
    @Query('sortBy') sortBy?: 'createdAt' | 'lastActiveAt',
    @Query('sortOrder') sortOrder?: 'ASC' | 'DESC',
  ) {
    this.verifyAdmin(auth);

    const result = await this.userService.findAll({
      type,
      phone,
      nickname,
      page: parseInt(page, 10),
      pageSize: parseInt(pageSize, 10),
      sortBy,
      sortOrder,
    });

    return {
      success: true,
      data: {
        items: result.items.map((user) => ({
          id: user.id,
          type: user.type,
          phone: user.phone,
          nickname: user.nickname,
          avatar: user.avatar,
          createdAt: user.createdAt,
          lastActiveAt: user.lastActiveAt,
        })),
        total: result.total,
        page: result.page,
        pageSize: result.pageSize,
        totalPages: result.totalPages,
      },
    };
  }

  /**
   * GET /users/admin/statistics
   * Get user statistics
   */
  @Get('statistics')
  async getUserStatistics(@Headers('authorization') auth: string) {
    this.verifyAdmin(auth);

    const countByType = await this.userService.countByType();
    const total =
      countByType[UserType.ANONYMOUS] + countByType[UserType.REGISTERED];

    return {
      success: true,
      data: {
        total,
        anonymous: countByType[UserType.ANONYMOUS],
        registered: countByType[UserType.REGISTERED],
        registrationRate:
          total > 0
            ? ((countByType[UserType.REGISTERED] / total) * 100).toFixed(1)
            : '0',
      },
    };
  }

  /**
   * GET /users/admin/search
   * Search users by keyword
   */
  @Get('search')
  async searchUsers(
    @Headers('authorization') auth: string,
    @Query('keyword') keyword: string,
    @Query('limit') limit = '10',
  ) {
    this.verifyAdmin(auth);

    if (!keyword || keyword.length < 2) {
      return {
        success: true,
        data: [],
      };
    }

    const users = await this.userService.searchUsers(
      keyword,
      parseInt(limit, 10),
    );

    return {
      success: true,
      data: users.map((user) => ({
        id: user.id,
        type: user.type,
        phone: user.phone,
        nickname: user.nickname,
        avatar: user.avatar,
        createdAt: user.createdAt,
        lastActiveAt: user.lastActiveAt,
      })),
    };
  }

  /**
   * GET /users/admin/:id
   * Get user detail by ID
   */
  @Get(':id')
  async getUserDetail(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
  ) {
    this.verifyAdmin(auth);

    const user = await this.userService.findById(id);

    return {
      success: true,
      data: {
        id: user.id,
        type: user.type,
        phone: user.phone,
        nickname: user.nickname,
        avatar: user.avatar,
        fingerprint: user.fingerprint,
        createdAt: user.createdAt,
        updatedAt: user.updatedAt,
        lastActiveAt: user.lastActiveAt,
      },
    };
  }
}
