import { Request, Response } from 'express';
import { Result } from '../../../shared/types/result';
import { ResponseCode } from '../../../shared/constants/enums';
import { handleResponse } from '../../../shared/utils/handle-response';
import { UserService } from '../services/user.service';
import { IUserCreate, IUserUpdate } from '../entities/user.entity';

export class UserController {
  private userService: UserService;

  constructor() {
    this.userService = new UserService();
  }

  /**
   * @openapi
   * /api/users:
   *   get:
   *     summary: Get all users
   *     description: Retrieve a list of all active users
   *     tags: [Users]
   *     responses:
   *       200:
   *         description: List of users retrieved successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   type: array
   *                   items:
   *                     $ref: '#/components/schemas/User'
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       400:
   *         description: Bad request
   */
  async getAll(req: Request, res: Response): Promise<void> {
    try {
      const result = await this.userService.getAll();
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to fetch users', error.message));
    }
  }

  /**
   * @openapi
   * /api/users/{id}:
   *   get:
   *     summary: Get user by ID
   *     description: Retrieve a specific user by their ID
   *     tags: [Users]
   *     parameters:
   *       - in: path
   *         name: id
   *         required: true
   *         schema:
   *           type: string
   *         description: User ID
   *     responses:
   *       200:
   *         description: User retrieved successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   $ref: '#/components/schemas/User'
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       404:
   *         description: User not found
   */
  async getById(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const result = await this.userService.getById(id);
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to fetch user', error.message));
    }
  }

  /**
   * @openapi
   * /api/users:
   *   post:
   *     summary: Create new user
   *     description: Create a new user account
   *     tags: [Users]
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             required:
   *               - email
   *               - username
   *               - password
   *             properties:
   *               email:
   *                 type: string
   *                 format: email
   *               username:
   *                 type: string
   *                 minLength: 3
   *               password:
   *                 type: string
   *                 minLength: 6
   *               firstName:
   *                 type: string
   *               lastName:
   *                 type: string
   *               phone:
   *                 type: string
   *               role:
   *                 type: string
   *                 enum: [user, admin, moderator]
   *     responses:
   *       201:
   *         description: User created successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   $ref: '#/components/schemas/User'
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       409:
   *         description: User already exists
   *       400:
   *         description: Bad request or missing required fields
   */
  async create(req: Request, res: Response): Promise<void> {
    try {
      const userData: IUserCreate = req.body;
      // Basic validation
      if (!userData.email || !userData.username || !userData.password) {
        handleResponse(res, Result.missingFields('Email, username, and password are required'));
        return;
      }
      const result = await this.userService.create(userData);
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to create user', error.message));
    }
  }

  /**
   * @openapi
   * /api/users/{id}:
   *   put:
   *     summary: Update user
   *     description: Update an existing user's information
   *     tags: [Users]
   *     parameters:
   *       - in: path
   *         name: id
   *         required: true
   *         schema:
   *           type: string
   *         description: User ID
   *     requestBody:
   *       required: true
   *       content:
   *         application/json:
   *           schema:
   *             type: object
   *             properties:
   *               firstName:
   *                 type: string
   *               lastName:
   *                 type: string
   *               phone:
   *                 type: string
   *               avatar:
   *                 type: string
   *               isActive:
   *                 type: boolean
   *               role:
   *                 type: string
   *                 enum: [user, admin, moderator]
   *     responses:
   *       200:
   *         description: User updated successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   $ref: '#/components/schemas/User'
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       404:
   *         description: User not found
   */
  async update(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userData: IUserUpdate = req.body;
      const result = await this.userService.update(id, userData);
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to update user', error.message));
    }
  }

  /**
   * @openapi
   * /api/users/{id}:
   *   delete:
   *     summary: Delete user
   *     description: Soft delete a user (sets status to 0)
   *     tags: [Users]
   *     parameters:
   *       - in: path
   *         name: id
   *         required: true
   *         schema:
   *           type: string
   *         description: User ID
   *     responses:
   *       200:
   *         description: User deleted successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   type: boolean
   *                   example: true
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       404:
   *         description: User not found
   */
  async delete(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const result = await this.userService.delete(id);
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to delete user', error.message));
    }
  }

  /**
   * @openapi
   * /api/users/profile:
   *   get:
   *     summary: Get user profile
   *     description: Get the current authenticated user's profile
   *     tags: [Users]
   *     security:
   *       - bearerAuth: []
   *     responses:
   *       200:
   *         description: User profile retrieved successfully
   *         content:
   *           application/json:
   *             schema:
   *               type: object
   *               properties:
   *                 Data:
   *                   $ref: '#/components/schemas/User'
   *                 StatusCode:
   *                   type: integer
   *                   example: 1000
   *       401:
   *         description: User not authenticated
   *       404:
   *         description: User not found
   */
  async getProfile(req: Request, res: Response): Promise<void> {
    try {
      // Assuming user ID is available from auth middleware
      const userId = (req as any).user?.id;
      if (!userId) {
        handleResponse(res, Result.unauthorized('User not authenticated'));
        return;
      }
      const result = await this.userService.getById(userId);
      handleResponse(res, result);
    } catch (error: any) {
      handleResponse(res, Result.error('Failed to fetch profile', error.message));
    }
  }
}

/**
 * @openapi
 * components:
 *   schemas:
 *     User:
 *       type: object
 *       properties:
 *         _id:
 *           type: string
 *           description: User ID
 *         email:
 *           type: string
 *           format: email
 *           description: User email address
 *         username:
 *           type: string
 *           description: Username
 *         firstName:
 *           type: string
 *           description: First name
 *         lastName:
 *           type: string
 *           description: Last name
 *         phone:
 *           type: string
 *           description: Phone number
 *         avatar:
 *           type: string
 *           description: Avatar URL
 *         isActive:
 *           type: boolean
 *           description: Whether user is active
 *         lastLoginAt:
 *           type: string
 *           format: date-time
 *           description: Last login timestamp
 *         emailVerified:
 *           type: boolean
 *           description: Whether email is verified
 *         phoneVerified:
 *           type: boolean
 *           description: Whether phone is verified
 *         role:
 *           type: string
 *           enum: [user, admin, moderator]
 *           description: User role
 *         permissions:
 *           type: array
 *           items:
 *             type: string
 *           description: User permissions
 *         status:
 *           type: integer
 *           description: User status (1 - active, 0 - deleted, -1 - suspended)
 *         createdAt:
 *           type: string
 *           format: date-time
 *           description: Creation timestamp
 *         updatedAt:
 *           type: string
 *           format: date-time
 *           description: Last update timestamp
 *       required:
 *         - email
 *         - username
 *         - isActive
 *         - emailVerified
 *         - phoneVerified
 *         - role
 *         - status
 *         - createdAt
 *         - updatedAt
 */ 