import { Request, Response } from 'express';
import { UserService } from '../services/user.service';
import { ResponseHandler } from '@utils/responseHandler';
import logger from '@utils/logger';

export class UserController {
  private userService: UserService;

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

  async getAllUsers(req: Request, res: Response): Promise<void> {
    try {
      const users = await this.userService.getAllUsers();

      const result = {
        users: users.map(u => ({
          userId: u.userId,
          email: u.email,
          displayName: u.displayName,
          department: u.department,
          designation: u.designation,
          isActive: u.isActive,
        })),
        total: users.length
      };

      ResponseHandler.success(res, result, 'All users fetched');
    } catch (error) {
      logger.error('Failed to fetch all users', { error });
      ResponseHandler.error(res, 'Failed to fetch all users', 500);
    }
  }

  async searchUsers(req: Request, res: Response): Promise<void> {
    try {
      const q = String(req.query.q || '').trim();
      const limit = Number(req.query.limit || 10);
      const source = String(req.query.source || 'default') as 'local' | 'okta' | 'default';
      const currentUserId = (req as any).user?.userId || (req as any).user?.id;

      const users = await this.userService.searchUsers(q, limit, currentUserId, source);

      const result = users.map(u => ({
        userId: (u as any).userId,
        email: (u as any).email,
        displayName: (u as any).displayName,
        firstName: (u as any).firstName,
        lastName: (u as any).lastName,
        department: (u as any).department,
        designation: (u as any).designation,
        isActive: (u as any).isActive,
      }));

      ResponseHandler.success(res, result, 'Users fetched');
    } catch (error) {
      logger.error('User search failed', { error });
      ResponseHandler.error(res, 'User search failed', 500);
    }
  }

  /**
   * Search users in Okta by displayName
   * GET /api/v1/users/search-by-displayname?displayName=John Doe
   * Used when creating claim requests to find manager by displayName
   */
  async searchByDisplayName(req: Request, res: Response): Promise<void> {
    try {
      const displayName = String(req.query.displayName || '').trim();

      if (!displayName) {
        ResponseHandler.error(res, 'displayName query parameter is required', 400);
        return;
      }

      const oktaUsers = await this.userService.searchOktaByDisplayName(displayName);

      const result = oktaUsers.map(u => ({
        userId: u.id,
        email: u.profile.email || u.profile.login,
        displayName: u.profile.displayName || `${u.profile.firstName || ''} ${u.profile.lastName || ''}`.trim(),
        firstName: u.profile.firstName,
        lastName: u.profile.lastName,
        department: u.profile.department,
        status: u.status,
      }));

      ResponseHandler.success(res, result, 'Users found by displayName');
    } catch (error: any) {
      logger.error('Search by displayName failed', { error });
      ResponseHandler.error(res, error.message || 'Search by displayName failed', 500);
    }
  }

  async getUserById(req: Request, res: Response): Promise<void> {
    try {
      const { userId } = req.params;
      const user = await this.userService.getUserById(userId);

      if (!user) {
        ResponseHandler.error(res, 'User not found', 404);
        return;
      }

      ResponseHandler.success(res, {
        userId: user.userId,
        email: user.email,
        displayName: user.displayName,
        firstName: user.firstName,
        lastName: user.lastName,
        department: user.department,
        isActive: user.isActive
      }, 'User fetched');
    } catch (error) {
      logger.error('Failed to fetch user by ID', { error });
      ResponseHandler.error(res, 'Failed to fetch user by ID', 500);
    }
  }

  /**
   * Ensure user exists in database (create if not exists)
   * Called when user is selected/tagged in the frontend
   */
  async ensureUserExists(req: Request, res: Response): Promise<void> {
    try {
      const { userId, email, displayName, firstName, lastName, department, phone } = req.body;

      if (!userId || !email) {
        ResponseHandler.error(res, 'userId and email are required', 400);
        return;
      }

      const user = await this.userService.ensureUserExists({
        userId,
        email,
        displayName,
        firstName,
        lastName,
        department,
        phone
      });

      ResponseHandler.success(res, {
        userId: user.userId,
        email: user.email,
        displayName: user.displayName,
        firstName: user.firstName,
        lastName: user.lastName,
        department: user.department,
        isActive: user.isActive
      }, 'User ensured in database');
    } catch (error: any) {
      logger.error('Ensure user failed', { error });
      ResponseHandler.error(res, error.message || 'Failed to ensure user', 500);
    }
  }
}


