import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  Req,
  HttpException,
  HttpStatus,
  UseInterceptors,
  UploadedFile,
  UploadedFiles,
  Query,
} from '@nestjs/common';
import { UserService } from './user.service';
import { UserEntity } from './entities/user.entity';
import { Public } from '../auth/public.decorator';
import { Request } from 'express';
import { JwtService } from '@nestjs/jwt';
import { v4 as uuidv4 } from 'uuid';
import {
  FileInterceptor,
  FileFieldsInterceptor,
} from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { promises as fs } from 'fs';
import { baseApiUrl } from '../../config/common';
import { RoleAccessService } from '../role_access/role_access.service';
import { ActivityLogsService } from '../activity_logs/activity_logs.service';
declare module 'express-session' {
  export interface SessionData {
    sessionIndex: string;
  }
}
import {
  ApiBearerAuth,
  ApiTags,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiOperation,
  ApiConsumes,
} from '@nestjs/swagger';

@ApiTags('users')
@ApiBearerAuth('access-token')
@Controller('users')
export class UserController {
  constructor(
    private readonly userService: UserService,
    private readonly jwtService: JwtService,
    @InjectRepository(UserEntity)
    private readonly userRepo: Repository<UserEntity>,
    private readonly roleAccessService: RoleAccessService,
    private readonly activityLogs: ActivityLogsService,
  ) {}

  private getBaseUrl(): string {
    // Use environment variable if available, otherwise use localhost for development
    return baseApiUrl || 'https://jobvumi.com/api';
    // return baseApiUrl || 'http://localhost:4000';
  }

  @Public()
  @Get()
  @ApiOperation({ summary: 'Get all users' })
  findAll(): Promise<UserEntity[]> {
    return this.userService.findAll();
  }
  // For Admin Dashboard
  @Public()
  @Get('list_users')
  @ApiOperation({ summary: 'List all users with pagination and filtering' })
  @ApiQuery({
    name: 'page',
    required: false,
    type: Number,
    description: 'Page number',
  })
  @ApiQuery({
    name: 'limit',
    required: false,
    type: Number,
    description: 'Items per page',
  })
  @ApiQuery({
    name: 'status',
    required: false,
    type: String,
    description: 'User status',
  })
  @ApiQuery({
    name: 'role',
    required: false,
    type: String,
    description: 'User role',
  })
  @ApiQuery({
    name: 'search',
    required: false,
    type: String,
    description: 'Search term for name, email, phone, company',
  })
  @ApiQuery({
    name: 'hasCompany',
    required: false,
    type: Boolean,
    description: 'Only return users with a linked company',
  })
  async listUsers(@Query() query: any) {
    const { page = 1, limit = 10, status, role, search, hasCompany } = query;
    return await this.userService.findAllWithQuery({
      page: Number(page),
      limit: Number(limit),
      status,
      role,
      search,
      hasCompany,
    });
  }

  // New filtered applicants endpoint
  @Public()
  @Get('filtered_applicants')
  @ApiOperation({ summary: 'Get filtered applicants' })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'status', required: false, type: String })
  @ApiQuery({ name: 'role', required: false, type: String, example: 'seeker' })
  @ApiQuery({ name: 'experience', required: false, type: String })
  @ApiQuery({ name: 'qualification', required: false, type: String })
  @ApiQuery({ name: 'roles', required: false, type: String })
  @ApiQuery({ name: 'city', required: false, type: String })
  @ApiQuery({ name: 'search', required: false, type: String })
  @ApiQuery({ name: 'cvLastUpdated', required: false, type: String })
  @ApiQuery({ name: 'availability', required: false, type: String })
  @ApiQuery({ name: 'jobTitle', required: false, type: String })
  @ApiQuery({ name: 'skills', required: false, type: String })
  @ApiQuery({
    name: 'onboardingStatus',
    required: false,
    type: String,
    enum: ['not_started', 'in_progress', 'completed'],
  })
  async getFilteredApplicants(@Query() query: any) {
    const {
      page = 1,
      limit = 10,
      status,
      role = 'seeker',
      experience,
      qualification,
      roles,
      city,
      search,
      cvLastUpdated,
      availability,
      jobTitle,
      skills,
      onboardingStatus,
    } = query;

    return await this.userService.findFilteredApplicants({
      page: Number(page),
      limit: Number(limit),
      status,
      role,
      experience,
      qualification,
      roles,
      city,
      search,
      cvLastUpdated,
      availability,
      jobTitle,
      skills,
      onboardingStatus,
    });
  }

  //  Update User API
  @Public()
  @Put('update_user/:id')
  @ApiOperation({ summary: 'Update user (and role access if operation role)' })
  @ApiParam({ name: 'id', type: Number })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        fullName: { type: 'string' },
        email: { type: 'string' },
        phone: { type: 'string' },
        role: { type: 'string' },
        status: { type: 'string' },
        moduleIds: { type: 'array', items: { type: 'number' } },
      },
    },
  })
  async updateUser(@Param('id') id: number, @Body() data: any) {
    try {
      if (data.role === 'operation') {
        // 🔹 Handle OPERATION → update users + role_access
        return await this.roleAccessService.updateUserWithRoleAccess(
          Number(id),
          data,
        );
      } else {
        //  Handle normal users
        const updatedUser = await this.userService.updateUser(Number(id), data);
        return {
          success: true,
          message: 'User updated successfully',
          user: updatedUser,
        };
      }
    } catch (err) {
      throw new HttpException(err.message, HttpStatus.BAD_REQUEST);
    }
  }

  // user.controller.ts
  @Public()
  @Put('update_status/:id')
  @ApiOperation({ summary: 'Update user status' })
  @ApiParam({ name: 'id', type: Number })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', enum: ['active', 'inactive', 'banned'] },
      },
    },
  })
  async updateStatus(
    @Param('id') id: number,
    @Body('status') status: 'active' | 'inactive' | 'banned',
  ) {
    try {
      return await this.userService.updateStatus(Number(id), status);
    } catch (err) {
      throw new HttpException(err.message, HttpStatus.BAD_REQUEST);
    }
  }
  @Public()
  @Get(':id')
  @ApiOperation({ summary: 'Get user by ID' })
  @ApiParam({ name: 'id', type: Number })
  async findOne(@Param('id') id: number) {
    const data = await this.userService.getOnboardingData(Number(id));
    if (data && data.user) {
      return {
        ...data.user,
        profilePictureUrl:
          data.user && data.user.profilePicture
            ? `${this.getBaseUrl()}/${data.user.profilePicture}`
            : null,
        seekerProfile: data.profile,
        address: data.address,
        educations: data.educations,
        experiences: data.experiences,
        resumes: data.resumes,
        skills: data.skills,
        languages: data.languages,
        certifications: data.certifications,
        social_links: data.social_links,
      };
    }

    const user = await this.userService.findOne(Number(id));
    return {
      ...user,
      profilePictureUrl:
        user && user.profilePicture
          ? `${this.getBaseUrl()}/${user.profilePicture}`
          : null,
    };
  }

  // @Public()
  // @Post()
  // @ApiOperation({ summary: 'Create user' })
  // @ApiBody({
  //   schema: {
  //     type: 'object',
  //     properties: {
  //       username: { type: 'string', example: 'john_doe' },
  //       email: { type: 'string', format: 'email', example: 'john@example.com' },
  //       password: { type: 'string', example: 'securePass123' },
  //       role: { type: 'string', enum: ['seeker', 'recruiter', 'admin', 'franchise', 'operation', 'trainer', 'associate'], default: 'seeker' },
  //       fullName: { type: 'string', example: 'John Doe' },
  //       phone: { type: 'string', example: '+1234567890' },
  //       secondary_phone: { type: 'string' },
  //       whatsapp_number: { type: 'string' },
  //       seekerType: { type: 'string', enum: ['entry_level', 'mid_level', 'professional'] }
  //     },
  //     required: ['username', 'email', 'password', 'role', 'fullName']
  //   }
  // })
  // create(@Body() userData: Partial<UserEntity>): Promise<UserEntity> {
  //   return this.userService.create(userData);
  // }

  @Public()
  @Put(':id')
  @ApiOperation({ summary: 'Update user' })
  @ApiParam({ name: 'id', type: Number })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        username: { type: 'string' },
        email: { type: 'string', format: 'email' },
        role: {
          type: 'string',
          enum: [
            'seeker',
            'recruiter',
            'admin',
            'franchise',
            'operation',
            'trainer',
            'associate',
          ],
        },
        fullName: { type: 'string' },
        phone: { type: 'string' },
        status: { type: 'string', enum: ['active', 'inactive', 'banned'] },
        profilePicture: { type: 'string' },
      },
    },
  })
  update(
    @Param('id') id: number,
    @Body() userData: Partial<UserEntity>,
  ): Promise<UserEntity> {
    return this.userService.update(Number(id), userData);
  }

  @Public()
  @Put(':id/profile_picture')
  @ApiOperation({ summary: 'Upload profile picture' })
  @ApiParam({ name: 'id', type: Number })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        profilePicture: {
          type: 'string',
          format: 'binary',
        },
      },
    },
  })
  @UseInterceptors(
    FileInterceptor('profilePicture', {
      storage: diskStorage({
        destination: './uploads/profile-pictures',
        filename: (req, file, cb) => {
          const uniqueSuffix =
            Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, uniqueSuffix + extname(file.originalname));
        },
      }),
      limits: { fileSize: 2 * 1024 * 1024 }, // 2MB limit
      fileFilter: (req, file, cb) => {
        if (!file.mimetype.match(/^image/)) {
          return cb(new Error('Only image files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadProfilePicture(
    @Param('id') id: number,
    @UploadedFile() file: Express.Multer.File,
  ) {
    if (!file) {
      throw new HttpException('File not provided', HttpStatus.BAD_REQUEST);
    }
    const profilePicturePath = file.path.replace(/\\/g, '/');
    await this.userRepo.update(id, { profilePicture: profilePicturePath });
    return { success: true, profile_picture: profilePicturePath };
  }

  @Public()
  @Get('onboarding/data/:id')
  @ApiOperation({
    summary: 'Get user onboarding data',
    description:
      'Retrieves specific fields for user and profile during onboarding steps',
  })
  @ApiParam({ name: 'id', type: Number })
  async getOnboardingData(@Param('id') id: number) {
    return this.userService.getOnboardingData(Number(id));
  }

  @Public()
  @Delete(':id/profile_picture')
  @ApiOperation({ summary: 'Delete profile picture' })
  @ApiParam({ name: 'id', type: Number })
  async deleteProfilePicture(@Param('id') id: number) {
    const user = await this.userService.findOne(Number(id));

    if (user && user.profilePicture) {
      const filePath = user.profilePicture;
      // 1. Update DB to remove the picture reference
      await this.userRepo.update(id, { profilePicture: null });
      // 2. Delete the actual file from the server
      try {
        await fs.unlink(filePath);
      } catch (err) {
        console.error(`Failed to delete image file: ${filePath}`, err);
      }
    }
    return { success: true, message: 'Profile picture deleted successfully' };
  }
  @Public()
  @Delete(':id')
  @ApiOperation({ summary: 'Delete user' })
  @ApiParam({ name: 'id', type: Number })
  remove(@Param('id') id: number): Promise<void> {
    return this.userService.remove(Number(id));
  }
  // ============================================================================
  // COMMENTED OUT: This endpoint is NOT used by the frontend
  // Frontend uses: POST /users/login_password and POST /users/login_otp instead
  // This is the legacy login endpoint that only supports email+password
  // The new endpoints support both email/phone with password/OTP
  // Last checked: 2025-12-30
  // ============================================================================
  // @Public()
  // @Post('/login')
  // @ApiOperation({ summary: 'Login', description: 'Standard login using email and password.' })
  // @ApiBody({
  //   schema: {
  //     type: 'object',
  //     properties: {
  //       email: { type: 'string', example: 'user@example.com' },
  //       password: { type: 'string', example: 'password123' },
  //     },
  //     required: ['email', 'password'],
  //   },
  // })
  // async login(@Body() body: { email: string; password: string }, @Req() req: Request) {
  //   try {
  //     const user = await this.userService.findByEmailWithPassword(
  //       body.email,
  //       body.password,
  //     );

  //     if (!user) {
  //       throw new HttpException(
  //         'Invalid email or password. Please check your credentials and try again.',
  //         HttpStatus.UNAUTHORIZED,
  //       );
  //     }
  //     // Fetch moduleAccess from the database
  //     // Add moduleAccess to the user object
  //     // Generate a session ID

  //     const sessionId = uuidv4();
  //     (req.session as any).sessionIndex = sessionId;

  //     const payload = {
  //       username: user.email,
  //       sub: user.id,
  //       sessionId: sessionId,
  //       ip: req.ip, // include client's IP address
  //       host: (req as any).hostname, // include client's host
  //       activeRole: user.role,
  //     };
  //     const access_token = this.jwtService.sign(payload, { expiresIn: '24h' }); // access token expires in 5 minutes
  //     const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' }); // refresh token expires in 7 days
  //     // Log auth_login activity
  //     try {
  //       const ip =
  //         (req.headers['x-forwarded-for'] as any) ||
  //         req.ip ||
  //         (req.connection && (req.connection as any).remoteAddress) ||
  //         null;
  //       const ua = (req.headers['user-agent'] as string) || '';
  //       const deviceType = /mobile/i.test(ua)
  //         ? 'mobile'
  //         : /tablet|ipad/i.test(ua)
  //           ? 'tablet'
  //           : 'desktop';
  //       await this.activityLogs.log({
  //         userId: user.id,
  //         userType: user.role,
  //         actionType: 'auth_login',
  //         actionName: 'Login Success',
  //         pageUrl: null,
  //         actionDetails: null,
  //         status: 'success',
  //         ipAddress: ip ? String(ip) : null,
  //         deviceType,
  //         browser: ua,
  //       });
  //     } catch (e) {
  //       // non-blocking
  //     }

  //     return {
  //       ...user,
  //       access_token,
  //       refresh_token,
  //     };
  //   } catch (exception) {
  //     throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
  //   }
  // }

  // Enhanced login with email or phone + password
  @Public()
  @Post('/login_password')
  @ApiOperation({ summary: 'Login with Email/Phone and Password' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        emailOrPhone: { type: 'string', example: 'user@example.com' },
        password: { type: 'string', example: 'password123' },
      },
      required: ['emailOrPhone', 'password'],
    },
  })
  async loginWithPassword(
    @Body() body: { emailOrPhone: string; password: string },
    @Req() req: Request,
  ) {
    try {
      const { emailOrPhone, password } = body;

      if (!emailOrPhone || !password) {
        throw new HttpException(
          'Email/Phone and password are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const user = await this.userService.loginWithPassword(
        emailOrPhone,
        password,
      );

      if (!user) {
        // Log failed login attempt
        try {
          const ip =
            (req.headers['x-forwarded-for'] as any) ||
            req.ip ||
            ((req.connection as any) &&
              (req.connection as any).remoteAddress) ||
            null;
          const ua = (req.headers['user-agent'] as string) || '';
          const deviceType = /mobile/i.test(ua)
            ? 'mobile'
            : /tablet|ipad/i.test(ua)
              ? 'tablet'
              : 'desktop';
          await this.activityLogs.log({
            userId: null,
            userType: 'guest',
            actionType: 'auth_failed',
            actionName: 'Login Failed',
            pageUrl: null,
            actionDetails: { emailOrPhone },
            status: 'failed',
            errorMessage: 'Invalid email/phone or password',
            ipAddress: ip ? String(ip) : null,
            deviceType,
            browser: ua,
          });
        } catch (e) {
          // non-blocking
        }
        throw new HttpException(
          'Invalid email/phone or password. Please check your credentials and try again.',
          HttpStatus.UNAUTHORIZED,
        );
      }

      const sessionId = uuidv4();
      (req.session as any).sessionIndex = sessionId;

      const payload = {
        username: user.email,
        sub: user.id,
        sessionId: sessionId,
        ip: req.ip,
        host: (req as any).hostname,
        activeRole: user.role,
      };

      const access_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      // Activity log: auth_login
      try {
        const ip =
          (req.headers['x-forwarded-for'] as any) ||
          req.ip ||
          ((req.connection as any) && (req.connection as any).remoteAddress) ||
          null;
        const ua = (req.headers['user-agent'] as string) || '';
        const deviceType = /mobile/i.test(ua)
          ? 'mobile'
          : /tablet|ipad/i.test(ua)
            ? 'tablet'
            : 'desktop';
        await this.activityLogs.log({
          userId: user.id,
          userType: user.role,
          actionType: 'auth_login',
          actionName: 'Login Success',
          pageUrl: null,
          actionDetails: null,
          status: 'success',
          ipAddress: ip ? String(ip) : null,
          deviceType,
          browser: ua,
        });
      } catch (e) {
        // non-blocking
      }

      return {
        ...user,
        access_token,
        refresh_token,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  // Login with email or phone + OTP
  @Public()
  @Post('/login_otp')
  @ApiOperation({ summary: 'Login with Email/Phone and OTP' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        emailOrPhone: { type: 'string', example: '9988776655' },
        otp: { type: 'string', example: '123456' },
      },
      required: ['emailOrPhone', 'otp'],
    },
  })
  async loginWithOTP(
    @Body() body: { emailOrPhone: string; otp: string; role?: string },
    @Req() req: Request,
  ) {
    try {
      const { emailOrPhone, otp, role } = body;

      if (!emailOrPhone || !otp) {
        throw new HttpException(
          'Email/Phone and OTP are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const user = await this.userService.loginWithOTP(emailOrPhone, otp, role);

      if (!user) {
        // Log failed OTP login attempt
        try {
          const ip =
            (req.headers['x-forwarded-for'] as any) ||
            req.ip ||
            ((req.connection as any) &&
              (req.connection as any).remoteAddress) ||
            null;
          const ua = (req.headers['user-agent'] as string) || '';
          const deviceType = /mobile/i.test(ua)
            ? 'mobile'
            : /tablet|ipad/i.test(ua)
              ? 'tablet'
              : 'desktop';
          await this.activityLogs.log({
            userId: null,
            userType: 'guest',
            actionType: 'auth_failed',
            actionName: 'OTP Login Failed',
            pageUrl: null,
            actionDetails: { emailOrPhone, role },
            status: 'failed',
            errorMessage: 'Invalid OTP',
            ipAddress: ip ? String(ip) : null,
            deviceType,
            browser: ua,
          });
        } catch (e) {
          // non-blocking
        }
        throw new HttpException(
          'Invalid email/phone or OTP. Please check your credentials and try again.',
          HttpStatus.UNAUTHORIZED,
        );
      }

      const sessionId = uuidv4();
      (req.session as any).sessionIndex = sessionId;

      const payload = {
        username: user.email,
        sub: user.id,
        sessionId: sessionId,
        ip: req.ip,
        host: (req as any).hostname,
        activeRole: user.role,
      };

      const access_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' });

      // Log successful OTP login
      try {
        const ip =
          (req.headers['x-forwarded-for'] as any) ||
          req.ip ||
          ((req.connection as any) && (req.connection as any).remoteAddress) ||
          null;
        const ua = (req.headers['user-agent'] as string) || '';
        const deviceType = /mobile/i.test(ua)
          ? 'mobile'
          : /tablet|ipad/i.test(ua)
            ? 'tablet'
            : 'desktop';
        await this.activityLogs.log({
          userId: user.id,
          userType: user.role,
          actionType: 'auth_login',
          actionName: 'OTP Login Success',
          pageUrl: null,
          actionDetails: null,
          status: 'success',
          ipAddress: ip ? String(ip) : null,
          deviceType,
          browser: ua,
        });
      } catch (e) {
        // non-blocking
      }

      return {
        ...user,
        access_token,
        refresh_token,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  // Send OTP for login
  // @Public()
  // @Post('/send_otp')
  // @ApiOperation({ summary: 'Send OTP for login' })
  // @ApiBody({
  //   schema: {
  //     type: 'object',
  //     properties: {
  //       emailOrPhone: { type: 'string', example: '9988776655' }
  //     },
  //     required: ['emailOrPhone']
  //   }
  // })
  // async sendOTP(@Body() body: { emailOrPhone: string }) {
  //   try {
  //     const { emailOrPhone } = body;

  //     if (!emailOrPhone) {
  //       throw new HttpException(
  //         'Email or phone number is required',
  //         HttpStatus.BAD_REQUEST,
  //       );
  //     }

  //     const result = await this.userService.generateAndSendOTP(emailOrPhone);

  //     if (!result.success) {
  //       throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
  //     }

  //     return {
  //       success: true,
  //       message: result.message,
  //     };
  //   } catch (exception) {
  //     throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
  //   }
  // }

  // Send OTP via email only (fallback when SMS is slow)
  @Public()
  @Post('/send_otp_email')
  @ApiOperation({ summary: 'Send OTP via Email (Fallback)' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'role'],
    },
  })
  async sendOTPEmail(@Body() body: { phone: string; role: string }) {
    try {
      const { phone, role } = body;

      if (!phone) {
        throw new HttpException(
          'Phone number is required',
          HttpStatus.BAD_REQUEST,
        );
      }

      if (!role) {
        throw new HttpException('Role is required', HttpStatus.BAD_REQUEST);
      }

      const result = await this.userService.sendEmailOTPByPhone(phone, role);

      if (!result.success) {
        throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
      }

      return {
        success: true,
        message: result.message,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  @Public()
  @Post('register')
  @ApiOperation({ summary: 'Register new user' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        full_name: { type: 'string', example: 'John Doe' },
        username: { type: 'string', example: 'johndoe' },
        email: { type: 'string', example: 'john@example.com' },
        password: { type: 'string', example: 'password123' },
        role: {
          type: 'string',
          enum: ['seeker', 'recruiter', 'associate'],
          example: 'seeker',
        },
        phone: { type: 'string', example: '9876543210' },
        companyName: {
          type: 'string',
          description: 'Required for recruiter',
          example: 'Acme Corp',
        },
        gst_number: { type: 'string', description: 'Optional for recruiter' },
        cin_number: { type: 'string', description: 'Optional for recruiter' },
      },
      required: ['full_name', 'username', 'email', 'password', 'role'],
    },
  })
  async register(@Body() data: any) {
    return this.userService.registerUser(data);
  }

  @Public()
  @Post('admin/register-and-link-company')
  @ApiOperation({
    summary: 'Admin: Register recruiter and link to seed company',
    description:
      'Creates a new recruiter user and links them to an existing seed/JV company',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        fullName: { type: 'string', example: 'Jane Smith' },
        email: { type: 'string', format: 'email', example: 'jane@example.com' },
        phone: { type: 'string', example: '+91-9999999999' },
        companyId: { type: 'number', example: 10 },
        gstNumber: { type: 'string', example: '29ABCDE1234F1Z5' },
        cinNumber: { type: 'string', example: 'U12345AB2020PTC123456' },
        sendWelcomeEmail: { type: 'boolean', example: true },
      },
      required: ['fullName', 'email', 'phone', 'companyId'],
    },
  })
  async registerRecruiterAndLinkCompany(@Body() data: any) {
    try {
      return await this.userService.registerRecruiterAndLinkCompany(data);
    } catch (error) {
      throw new HttpException(
        error.message || 'Failed to register recruiter',
        HttpStatus.BAD_REQUEST,
      );
    }
  }
  @Public()
  @Post('/logout')
  @ApiOperation({ summary: 'Logout user' })
  async logout(
    @Req() req: Request,
    @Body() body: { userId?: number; userType?: string },
  ) {
    // Log logout activity
    try {
      const ip =
        (req.headers['x-forwarded-for'] as any) ||
        req.ip ||
        ((req.connection as any) && (req.connection as any).remoteAddress) ||
        null;
      const ua = (req.headers['user-agent'] as string) || '';
      const deviceType = /mobile/i.test(ua)
        ? 'mobile'
        : /tablet|ipad/i.test(ua)
          ? 'tablet'
          : 'desktop';
      await this.activityLogs.log({
        userId: body.userId || null,
        userType: body.userType || 'guest',
        actionType: 'auth_logout',
        actionName: 'Logout',
        pageUrl: null,
        actionDetails: null,
        status: 'success',
        ipAddress: ip ? String(ip) : null,
        deviceType,
        browser: ua,
      });
    } catch (e) {
      // non-blocking
    }

    req.session.destroy((err) => {
      if (err) {
        throw new HttpException(
          'Logout failed',
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }
    });
    return { message: 'Logged out successfully' };
  }

  // Test OTP entity
  @Public()
  @Get('/test_otp')
  async testOtp() {
    try {
      const result = await this.userService.testOtpEntity();
      return result;
    } catch (error) {
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  // Test password update
  @Public()
  @Post('/test_password_update')
  @ApiOperation({ summary: 'Test Password Update' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        newPassword: { type: 'string' },
      },
      required: ['userId', 'newPassword'],
    },
  })
  async testPasswordUpdate(
    @Body() body: { userId: number; newPassword: string },
  ) {
    try {
      const { userId, newPassword } = body;
      // console.log(`Testing password update for user ${userId} with password: ${newPassword}`);

      const updateResult = await this.userRepo.update(userId, {
        password: newPassword,
      });

      // console.log(`Test password update result:`, updateResult);

      // Verify the update
      const updatedUser = await this.userRepo
        .createQueryBuilder('user')
        .addSelect('user.password')
        .where('user.id = :userId', { userId })
        .getOne();

      return {
        success: true,
        updateResult,
        updatedPassword: updatedUser?.password,
        message: 'Password update test completed',
      };
    } catch (error) {
      console.error('Test password update error:', error);
      throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  // Forgot password - send OTP
  @Public()
  @Post('/forgot_password_send_otp')
  @ApiOperation({ summary: 'Send OTP for Forgot Password' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        emailOrPhone: { type: 'string', example: 'user@example.com' },
      },
      required: ['emailOrPhone'],
    },
  })
  async forgotPasswordSendOTP(@Body() body: { emailOrPhone: string }) {
    try {
      const { emailOrPhone } = body;

      if (!emailOrPhone) {
        throw new HttpException(
          'Email or phone number is required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.forgotPasswordSendOTP(emailOrPhone);

      return {
        success: true,
        message: result.message,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  // Verify OTP only (for forgot password flow)
  @Public()
  @Post('/verify_otp')
  @ApiOperation({ summary: 'Verify OTP' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        emailOrPhone: { type: 'string', example: '9988776655' },
        otp: { type: 'string', example: '123456' },
      },
      required: ['emailOrPhone', 'otp'],
    },
  })
  async verifyOTP(@Body() body: { emailOrPhone: string; otp: string }) {
    try {
      const { emailOrPhone, otp } = body;

      if (!emailOrPhone || !otp) {
        throw new HttpException(
          'Email/Phone and OTP are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.verifyOTP(emailOrPhone, otp);

      return {
        success: result.success,
        message: result.message,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  // Forgot password - verify OTP and reset password
  @Public()
  @Post('/forgot_password_reset')
  @ApiOperation({ summary: 'Reset Password with OTP' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        emailOrPhone: { type: 'string', example: '9988776655' },
        otp: { type: 'string', example: '123456' },
        newPassword: { type: 'string', example: 'newPassword123' },
      },
      required: ['emailOrPhone', 'otp', 'newPassword'],
    },
  })
  async forgotPasswordReset(
    @Body() body: { emailOrPhone: string; otp: string; newPassword: string },
  ) {
    try {
      const { emailOrPhone, otp, newPassword } = body;

      // console.log('Forgot password reset request:', { emailOrPhone, otp, newPasswordLength: newPassword?.length });

      if (!emailOrPhone || !otp || !newPassword) {
        throw new HttpException(
          'Email/Phone, OTP, and new password are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.forgotPasswordReset(
        emailOrPhone,
        otp,
        newPassword,
      );

      // console.log('Forgot password reset result:', result);

      return {
        success: result.success,
        message: result.message,
      };
    } catch (exception) {
      console.error('Forgot password reset exception:', exception);
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  // ═══════════════════════════════════════════════════════════
  // NEW OTP AUTHENTICATION ENDPOINTS
  // Added for multi-role OTP-based login/registration
  // ═══════════════════════════════════════════════════════════

  /**
   * Check if phone exists and return all roles
   */
  @Public()
  @Post('/check_phone')
  @ApiOperation({
    summary: 'Check if phone exists',
    description:
      'First step of authentication. Checks if the phone number is already registered to determine if the user should login or register.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
      },
      required: ['phone'],
    },
  })
  async checkPhone(@Body() body: { phone: string }) {
    try {
      const { phone } = body;

      if (!phone) {
        throw new HttpException(
          'Phone number is required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.checkPhoneExists(phone);
      return result;
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Send OTP for specific role (existing user login)
   */
  @Public()
  @Post('/send_otp_for_role')
  @ApiOperation({ summary: 'Send OTP for specific role' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'role'],
    },
  })
  async sendOTPForRole(@Body() body: { phone: string; role: string }) {
    try {
      const { phone, role } = body;

      if (!phone || !role) {
        throw new HttpException(
          'Phone and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.sendOTPForRole(phone, role);
      return result;
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Verify OTP and login for specific role
   */
  @Public()
  @Post('/verify_otp_and_login')
  @ApiOperation({ summary: 'Verify OTP and Login (Role Based)' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
        otp: { type: 'string', example: '123456' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'otp', 'role'],
    },
  })
  async verifyOTPAndLogin(
    @Body() body: { phone: string; otp: string; role: string },
    @Req() req: Request,
  ) {
    try {
      const { phone, otp, role } = body;

      if (!phone || !otp || !role) {
        throw new HttpException(
          'Phone, OTP and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const user = await this.userService.loginWithOTPAndRole(phone, otp, role);

      if (!user) {
        throw new HttpException(
          'Invalid OTP or credentials',
          HttpStatus.UNAUTHORIZED,
        );
      }

      // Track device type and initialize web onboarding step if moving from Mobile to Web
      const ua = req.headers['user-agent'] || '';
      const deviceType = /mobile/i.test(ua)
        ? 'mobile'
        : /tablet|ipad/i.test(ua)
          ? 'tablet'
          : 'desktop';

      const updates: any = {};
      if (
        user.onboardingStatus === 'in_progress' &&
        (user.onboardingStep === 0 || user.onboardingStep === null)
      ) {
        updates.onboardingStep = 1;
        user.onboardingStep = 1; // Update local object for response
      }

      if (Object.keys(updates).length > 0 && user.id && !isNaN(user.id)) {
        await this.userService.update(user.id, updates);
      }

      // Generate JWT tokens (same pattern as existing login)
      const sessionId = uuidv4();
      (req.session as any).sessionIndex = sessionId;

      const payload = {
        username: user.email || user.phone,
        sub: user.id,
        sessionId: sessionId,
        ip: req.ip,
        host: (req as any).hostname,
        activeRole: user.role,
      };

      const access_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' });

      // NEW: Determine redirect based on onboarding status

      let redirectPath = '/dashboard';
      if (
        user.onboardingStatus === 'in_progress' ||
        user.onboardingStatus === 'not_started' ||
        user.onboardingStep === 0
      ) {
        // User has incomplete onboarding, redirect to onboarding
        redirectPath =
          user.role === 'seeker'
            ? '/seeker/onboarding'
            : user.role === 'recruiter'
              ? '/recruiter/onboarding'
              : '/dashboard';
      } else {
        // User completed onboarding or is legacy user, redirect to dashboard
        redirectPath =
          user.role === 'seeker'
            ? '/seeker/dashboard'
            : user.role === 'recruiter'
              ? '/recruiter/dashboard'
              : '/dashboard';
      }

      // console.log('DEBUG: login redirect check', { role: user.role, status: user.onboardingStatus, path: redirectPath });

      return {
        ...user,
        access_token,
        refresh_token,
        // NEW: Include onboarding fields
        onboarding_status: user.onboardingStatus,
        onboarding_step: user.onboardingStep,
        selected_role_category: user.selectedRoleCategory,
        redirect: redirectPath,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Send registration OTP for new users
   */
  @Public()
  @Post('/send_registration_otp')
  @ApiOperation({
    summary: 'Send OTP for Registration',
    description:
      'Initiates the registration process for a new user (Seeker/Employer). Sends an OTP to the provided phone number.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
        role: {
          type: 'string',
          example: 'seeker',
          enum: ['seeker', 'recruiter', 'franchise'],
        },
        category: {
          type: 'string',
          example: 'white_collar',
          enum: ['white_collar', 'blue_collar'],
          description:
            'Required for seekers only. white_collar=Tech, blue_collar=Non-Tech',
        },
      },
      required: ['phone', 'role'],
    },
  })
  async sendRegistrationOTP(
    @Body()
    body: {
      phone: string;
      role: string;
      category?: 'white_collar' | 'blue_collar';
    },
  ) {
    try {
      const { phone, role, category } = body;

      if (!phone || !role) {
        throw new HttpException(
          'Phone and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Validate role
      const validRoles = ['seeker', 'recruiter', 'franchise'];
      if (!validRoles.includes(role)) {
        throw new HttpException('Invalid role', HttpStatus.BAD_REQUEST);
      }

      // NOTE: Category is now optional during OTP sending
      // It will be provided after OTP verification via the /update-category endpoint

      const result = await this.userService.sendRegistrationOTP(
        phone,
        role,
        // category,
      );
      return result;
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Verify registration OTP
   */
  @Public()
  @Post('/verify_registration_otp')
  @ApiOperation({
    summary: 'Verify Registration OTP',
    description:
      'Verifies the OTP for a new user. If successful, returns user data with onboarding status and redirect path.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9988776655' },
        otp: { type: 'string', example: '123456' },
        role: {
          type: 'string',
          example: 'seeker',
          enum: ['seeker', 'recruiter', 'franchise'],
        },
      },
      required: ['phone', 'otp', 'role'],
    },
  })
  async verifyRegistrationOTP(
    @Body() body: { phone: string; otp: string; role: string },
    @Req() req: Request,
  ) {
    try {
      const { phone, otp, role } = body;

      if (!phone || !otp || !role) {
        throw new HttpException(
          'Phone, OTP and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const ua = req.headers['user-agent'] || '';
      const deviceType = /mobile/i.test(ua)
        ? 'mobile'
        : /tablet|ipad/i.test(ua)
          ? 'tablet'
          : 'desktop';

      const verified = await this.userService.verifyRegistrationOTP(
        phone,
        otp,
        role,
        'web',
        deviceType,
      );

      if (!verified) {
        throw new HttpException(
          'Invalid or expired OTP',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Fetch the created user to return full data
      const user = await this.userService.findByPhoneAndRole(phone, role);

      if (!user) {
        throw new HttpException(
          'User not found after verification',
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      return {
        success: true,
        verified: true,
        user: {
          id: user.id,
          phone: user.phone,
          role: user.role,
          fullName: user.fullName,
          onboarding_status: user.onboardingStatus,
          onboarding_step: user.onboardingStep,
          selected_role_category: user.selectedRoleCategory,
        },
        redirect:
          role === 'seeker'
            ? '/seeker/onboarding'
            : role === 'recruiter'
              ? '/recruiter/onboarding'
              : '/dashboard',
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Update seeker category after OTP verification
   */
  @Public()
  @Post('/update-category')
  @ApiOperation({
    summary: 'Update Seeker Category',
    description:
      'Updates the selected_role_category for a seeker after OTP verification',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number', example: 123 },
        category: {
          type: 'string',
          example: 'white_collar',
          enum: ['white_collar', 'blue_collar'],
        },
      },
      required: ['userId', 'category'],
    },
  })
  async updateCategory(
    @Body() body: { userId: number; category: 'white_collar' | 'blue_collar' },
  ) {
    try {
      const { userId, category } = body;

      if (!userId || !category) {
        throw new HttpException(
          'User ID and category are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Validate category
      if (category !== 'white_collar' && category !== 'blue_collar') {
        throw new HttpException(
          'Invalid category. Must be white_collar or blue_collar',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Update the user's selected_role_category
      await this.userRepo.update(userId, {
        selectedRoleCategory: category,
      });

      // Fetch updated user
      const user = await this.userService.findOne(userId);

      if (!user) {
        throw new HttpException('User not found', HttpStatus.NOT_FOUND);
      }

      return {
        success: true,
        message: 'Category updated successfully',
        user: {
          id: user.id,
          selected_role_category: user.selectedRoleCategory,
        },
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Send reactivation OTP for inactive users
   */
  @Public()
  @Post('/send_reactivation_otp')
  @ApiOperation({ summary: 'Send OTP for account reactivation' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9876543210' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'role'],
    },
  })
  async sendReactivationOTP(@Body() body: { phone: string; role: string }) {
    try {
      const { phone, role } = body;

      if (!phone || !role) {
        throw new HttpException(
          'Phone and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Validate role
      const validRoles = ['seeker', 'recruiter', 'franchise'];
      if (!validRoles.includes(role)) {
        throw new HttpException('Invalid role', HttpStatus.BAD_REQUEST);
      }

      const result = await this.userService.sendReactivationOTP(phone, role);
      return result;
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Verify reactivation OTP and activate account
   */
  @Public()
  @Post('/verify_reactivation_otp')
  @ApiOperation({ summary: 'Verify OTP and reactivate account' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9876543210' },
        otp: { type: 'string', example: '1234' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'otp', 'role'],
    },
  })
  async verifyReactivationOTP(
    @Body() body: { phone: string; otp: string; role: string },
    @Req() req: Request,
  ) {
    try {
      const { phone, otp, role } = body;

      if (!phone || !otp || !role) {
        throw new HttpException(
          'Phone, OTP and role are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const verified = await this.userService.verifyReactivationOTP(
        phone,
        otp,
        role,
      );

      if (!verified) {
        throw new HttpException(
          'Invalid or expired OTP',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Get the reactivated user (with status='active' filter to ensure fresh data)
      const user = await this.userService.findByPhoneAndRole(phone, role);

      if (!user || user.status !== 'active') {
        throw new HttpException(
          'User not found or not activated after reactivation',
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      // Generate JWT tokens (same pattern as existing login)
      const sessionId = uuidv4();
      (req.session as any).sessionIndex = sessionId;

      const payload = {
        username: user.email || user.phone,
        sub: user.id,
        sessionId: sessionId,
        ip: req.ip,
        host: (req as any).hostname,
        activeRole: user.role,
      };

      const access_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' });

      return {
        success: true,
        verified: true,
        phone: phone,
        role: role,
        ...user,
        access_token,
        refresh_token,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Send reactivation OTP via email (fallback)
   */
  @Public()
  @Post('/send_reactivation_otp_email')
  @ApiOperation({ summary: 'Send reactivation OTP via Email' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        phone: { type: 'string', example: '9876543210' },
        role: { type: 'string', example: 'seeker' },
      },
      required: ['phone', 'role'],
    },
  })
  async sendReactivationOTPEmail(
    @Body() body: { phone: string; role: string },
  ) {
    try {
      const { phone, role } = body;

      if (!phone) {
        throw new HttpException(
          'Phone number is required',
          HttpStatus.BAD_REQUEST,
        );
      }

      if (!role) {
        throw new HttpException('Role is required', HttpStatus.BAD_REQUEST);
      }

      const result = await this.userService.sendReactivationOTPEmail(
        phone,
        role,
      );

      if (!result.success) {
        throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
      }

      return {
        success: true,
        message: result.message,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Check if email exists for a different phone number
   * Used during seeker onboarding for live email validation
   */
  @Public()
  @Post('/check_email_for_phone')
  @ApiOperation({ summary: 'Check if email is linked to another phone' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        email: { type: 'string' },
        phone: { type: 'string' },
        userId: { type: 'number' },
      },
      required: ['email'],
    },
  })
  async checkEmailForPhone(
    @Body() body: { email: string; phone?: string; userId?: number },
  ) {
    try {
      const { email, phone, userId } = body;

      if (!email) {
        throw new HttpException('Email is required', HttpStatus.BAD_REQUEST);
      }

      const result = await this.userService.checkEmailExistsForDifferentPhone(
        email,
        phone || '',
        userId,
      );
      return result;
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Complete onboarding and create user account
   */
  @Public()
  @Post('/complete_onboarding')
  @ApiOperation({
    summary: 'Complete Onboarding & Create Account',
    description:
      'Final step of registration. Creates the User account and Profile after OTP verification. Accepts multipart/form-data for file uploads (logo, banner).',
  })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        full_name: { type: 'string' },
        email: { type: 'string' },
        phone: { type: 'string' },
        secondary_phone: { type: 'string' },
        whatsapp_number: { type: 'string' },
        username: { type: 'string' },
        role: {
          type: 'string',
          enum: ['seeker', 'recruiter', 'franchise', 'associate'],
        },
        seeker_type: {
          type: 'string',
          enum: ['entry_level', 'mid_level', 'professional'],
        },
        status: { type: 'string', enum: ['active', 'inactive', 'banned'] },
        profile_picture: { type: 'string' },
        company_name: {
          type: 'string',
          description: 'Updates linked company name',
        },

        // Recruiter/Company Specific
        professionalTitle: { type: 'string' },
        experienceId: { type: 'number' },
        educationId: { type: 'number' },
        dateOfBirth: { type: 'string' },
        gender: { type: 'string' },
        maritalStatus: { type: 'string' },
      },
    },
  })
  @UseInterceptors(
    FileFieldsInterceptor([
      { name: 'logo', maxCount: 1 },
      { name: 'banner', maxCount: 1 },
    ]),
  )
  async completeOnboarding(
    @Body() data: any,
    @UploadedFiles()
    files: {
      logo?: Express.Multer.File[];
      banner?: Express.Multer.File[];
    },
    @Req() req: Request,
  ) {
    try {
      // Add files to data object
      if (files?.logo?.[0]) {
        data.logoFile = files.logo[0];
      }
      if (files?.banner?.[0]) {
        data.bannerFile = files.banner[0];
      }

      const user = await this.userService.completeOnboarding(data);

      if (!user) {
        throw new HttpException(
          'Failed to create account',
          HttpStatus.INTERNAL_SERVER_ERROR,
        );
      }

      // Generate JWT tokens (same pattern as existing login)
      const sessionId = uuidv4();
      (req.session as any).sessionIndex = sessionId;

      const payload = {
        username: user.email || user.phone,
        sub: user.id,
        sessionId: sessionId,
        ip: req.ip,
        host: (req as any).hostname,
        activeRole: user.role,
      };

      const access_token = this.jwtService.sign(payload, { expiresIn: '24h' });
      const refresh_token = this.jwtService.sign(payload, { expiresIn: '24h' });

      // Get updated user data with profilePicture
      const updatedUser = await this.userService.findOne(user.id);

      return {
        ...updatedUser,
        access_token,
        refresh_token,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Update onboarding data progressively (called on each "Next" click)
   */
  @Public()
  @Put('/onboarding/data')
  @ApiOperation({
    summary: 'Update Onboarding Data Progressively',
    description:
      'Saves onboarding data as the user progresses through steps. Called when clicking "Next" button.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        step: { type: 'number' }, // Added for atomic update
        fullName: { type: 'string' },
        email: { type: 'string' },
        phone: { type: 'string' },
        professionalTitle: { type: 'string' },
        biography: { type: 'string' },
        personalWebsite: { type: 'string' },
        availability: { type: 'string' },
        gender: { type: 'string' },
        maritalStatus: { type: 'string' },
        dateOfBirth: { type: 'string' },
        experiencesId: { type: 'string' },
        educationId: { type: 'string' },
        professionId: { type: 'string' },
        skillsIds: { type: 'array', items: { type: 'number' } },
        languagesIds: { type: 'array', items: { type: 'number' } },
        experiences: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              company: { type: 'string' },
              department: { type: 'string' },
              designation: { type: 'string' },
              startDate: { type: 'string' },
              endDate: { type: 'string' },
              current: { type: 'boolean' },
              responsibilities: { type: 'string' },
            },
          },
        },
        educations: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              education_id: { type: 'string' },
              degree: { type: 'string' },
              year: { type: 'string' },
              notes: { type: 'string' },
            },
          },
        },
        permanentAddress: { type: 'string' },
        permanentPincode: { type: 'string' },
        permanentCountryId: { type: 'string' },
        permanentStateId: { type: 'string' },
        permanentCityId: { type: 'string' },
        permanentAreaId: { type: 'string' },
        communicationAddress: { type: 'string' },
        communicationPincode: { type: 'string' },
        communicationCountryId: { type: 'string' },
        communicationStateId: { type: 'string' },
        communicationCityId: { type: 'string' },
        communicationAreaId: { type: 'string' },
      },
      required: ['userId'],
    },
  })
  async updateOnboardingData(@Body() data: any) {
    try {
      // console.log('Received onboarding data update:', JSON.stringify(data, null, 2));
      const { userId, ...onboardingData } = data;

      if (!userId) {
        throw new HttpException('User ID is required', HttpStatus.BAD_REQUEST);
      }

      const result = await this.userService.updateOnboardingData(
        userId,
        onboardingData,
      );

      return {
        success: true,
        message: 'Onboarding data updated successfully',
        ...result,
      };
    } catch (exception) {
      console.error('Error updating onboarding data:', exception);
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Update onboarding step
   */
  @Public()
  @Put('/onboarding/step')
  @ApiOperation({
    summary: 'Update Onboarding Step',
    description: 'Updates the current onboarding step for a user.',
  })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        step: { type: 'number' },
      },
      required: ['userId', 'step'],
    },
  })
  async updateOnboardingStep(@Body() data: { userId: number; step: number }) {
    try {
      const { userId, step } = data;

      if (!userId || step === undefined) {
        throw new HttpException(
          'User ID and step are required',
          HttpStatus.BAD_REQUEST,
        );
      }

      const result = await this.userService.updateOnboardingStep(userId, step);

      return {
        success: true,
        message: 'Onboarding step updated successfully',
        ...result,
      };
    } catch (exception) {
      throw new HttpException(exception.message, HttpStatus.BAD_REQUEST);
    }
  }

  /**
   * Mark onboarding as completed (for existing users)
   */
  @Public()
  @Put('onboarding/complete')
  async markOnboardingComplete(@Body() body: { userId: number }) {
    try {
      await this.userService.markOnboardingComplete(body.userId);
      return { success: true, message: 'Onboarding marked as complete' };
    } catch (error) {
      return { success: false, message: error.message };
    }
  }
}
