import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  Request,
  HttpException,
  HttpStatus,
  Res,
  Req,
} from '@nestjs/common';
import { Public } from '../auth/public.decorator';
import { DashboardService } from './dashboard.service';
import { AnalyticsService } from '../analytics/analytics.service';
import { ActivityLogsService } from '../activity_logs/activity_logs.service';
import { UseInterceptors, UploadedFile } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import * as path from 'path';
import { extname } from 'path';
import * as fs from 'fs';
import { Response } from 'express';
import {
  ApiBearerAuth,
  ApiTags,
  ApiBody,
  ApiParam,
  ApiQuery,
  ApiOperation,
  ApiConsumes,
} from '@nestjs/swagger';
import { MulterError } from 'multer';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { SeekerProfiles } from '../seeker_profiles/entities/seeker_profiles.entity';
import { EmailService } from '../email/email.service';

@ApiTags('dashboard')
@ApiBearerAuth('access-token')
@Controller('dashboard')
export class DashboardController {
  constructor(
    private readonly dashboardService: DashboardService,
    private readonly analyticsService: AnalyticsService,
    private readonly activityLogsService: ActivityLogsService,
    @InjectRepository(SeekerProfiles)
    private readonly seekerProfileRepository: Repository<SeekerProfiles>,
    private readonly emailService: EmailService,
  ) {}

  // Seeker Dashboard Endpoints
  @Public()
  @Get('seeker/overview')
  @ApiOperation({ summary: 'Get Seeker Overview' })
  @ApiQuery({ name: 'userId', required: true, type: String })
  async getSeekerOverview(@Query('userId') userId: string) {
    return await this.dashboardService.getSeekerOverview(userId);
  }

  @Public()
  @Get('seeker/applied_jobs')
  @ApiOperation({ summary: 'Get Seeker Applied Jobs' })
  @ApiQuery({ name: 'userId', required: true, type: String })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'status', required: false, type: String })
  async getSeekerAppliedJobs(@Query('userId') userId: string, @Query() query) {
    const { page = 1, limit = 10, status } = query;
    return await this.dashboardService.getSeekerAppliedJobs(userId, {
      page,
      limit,
      status,
    });
  }

  @Public()
  @Get('seeker/applied_jobs/stats')
  @ApiOperation({ summary: 'Get Seeker Applied Jobs Stats' })
  @ApiQuery({ name: 'userId', required: true, type: String })
  async getSeekerAppliedJobsStats(@Query('userId') userId: string) {
    return await this.dashboardService.getSeekerAppliedJobsStats(userId);
  }

  @Public()
  @Get('seeker/favorite_jobs')
  async getSeekerFavoriteJobs(@Query('userId') userId: string, @Query() query) {
    const page = query.page ? Number(query.page) : 1;
    const limit = query.limit ? Number(query.limit) : 10;
    return await this.dashboardService.getSeekerFavoriteJobs(userId, {
      page,
      limit,
    });
  }
  // --- seeker applied jobs CRUD ---
  @Public()
  @Get('seeker/applied_jobs/list')
  async getSeekerAppliedJobsList(@Query('userId') userId: string) {
    return await this.dashboardService.fetchAppliedJobs(userId);
  }

  @Public()
  @Post('seeker/apply_job')
  @ApiOperation({ summary: 'Apply for Job' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'string' },
        jobPostId: { type: 'string' },
        coverLetter: { type: 'string' },
        resume_id: {
          type: 'number',
          description: 'ID of the resume to attach',
        },
      },
      required: ['userId', 'jobPostId', 'resume_id'],
    },
  })
  async applyForJob(@Body() data: any) {
    const userId = data.userId;
    return await this.dashboardService.applyForJob(
      userId,
      data.jobPostId,
      data.coverLetter,
      data.resumeId || data.resume_id,
    );
  }

  // --- seeker favorite jobs CRUD ---
  @Public()
  @Get('seeker/favorite_jobs/list')
  async getSeekerFavoriteJobsList(@Query('userId') userId: string) {
    return await this.dashboardService.fetchBookmarkedJobs(userId);
  }

  @Public()
  @Post('seeker/favorite_jobs/bookmark')
  @ApiOperation({ summary: 'Bookmark Job' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: { userId: { type: 'string' }, jobPostId: { type: 'string' } },
      required: ['userId', 'jobPostId'],
    },
  })
  async bookmarkJob(
    @Body('userId') userId: string,
    @Body('jobPostId') jobPostId: string,
  ) {
    // console.log('bookmarkJob', userId, jobPostId);
    return await this.dashboardService.bookmarkJob(userId, jobPostId);
  }

  @Public()
  @Delete('seeker/favorite_jobs/unbookmark')
  async unbookmarkJob(
    @Query('userId') userId: string,
    @Query('jobPostId') jobPostId: string,
  ) {
    return await this.dashboardService.unbookmarkJob(userId, jobPostId);
  }
  @Public()
  @Get('seeker/favorite_jobs/is_bookmarked')
  async isBookmarked(
    @Query('userId') userId: string,
    @Query('jobPostId') jobPostId: string,
  ) {
    return await this.dashboardService.isJobBookmarked(userId, jobPostId);
  }

  // Franchise Dashboard Endpoints
  @Public()
  @Get('franchise/:franchiseId/overview')
  @ApiOperation({ summary: 'Get Franchise Overview' })
  @ApiParam({ name: 'franchiseId', type: String })
  async getFranchiseOverview(@Param('franchiseId') franchiseId: string) {
    return await this.dashboardService.getFranchiseOverview(
      parseInt(franchiseId),
    );
  }

  @Public()
  @Get('franchise/:franchiseId/companies')
  async getFranchiseCompanies(
    @Param('franchiseId') franchiseId: string,
    @Query() query,
  ) {
    const page = query.page ? Number(query.page) : 1;
    const limit = query.limit ? Number(query.limit) : 10;
    return await this.dashboardService.getFranchiseCompanies(
      parseInt(franchiseId),
      { page, limit },
    );
  }

  @Public()
  @Get('franchise/:franchiseId/companies/overview')
  async getFranchiseCompaniesForOverview(
    @Param('franchiseId') franchiseId: string,
  ) {
    return await this.dashboardService.getFranchiseCompaniesForOverview(
      parseInt(franchiseId),
    );
  }

  @Public()
  @Post('franchise/:franchiseId/add_company')
  @ApiOperation({ summary: 'Add Company to Franchise' })
  @ApiParam({ name: 'franchiseId', type: String })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        companyName: { type: 'string' },
        email: { type: 'string', format: 'email' },
        phone: { type: 'string' },
        password: { type: 'string' },
        industry_id: { type: 'number' },
        about: { type: 'string' },
        location: { type: 'string' },
        website: { type: 'string' },
      },
      required: ['companyName', 'email', 'password'],
    },
  })
  async addCompanyForFranchise(
    @Param('franchiseId') franchiseId: string,
    @Body() companyData: any,
  ) {
    return await this.dashboardService.addCompanyForFranchise(
      parseInt(franchiseId),
      companyData,
    );
  }

  @Public()
  @Get('company/:companyId/recent_activity')
  async getCompanyRecentActivity(@Param('companyId') companyId: string) {
    return await this.dashboardService.getCompanyRecentActivity(
      parseInt(companyId),
    );
  }

  @Public()
  @Get('company/:companyId/details')
  async getCompanyDetails(@Param('companyId') companyId: string) {
    return await this.dashboardService.getCompanyDetails(parseInt(companyId));
  }

  @Public()
  @Get('company/:companyId/jobs')
  async getCompanyJobs(
    @Param('companyId') companyId: string,
    @Query('page') page: string = '1',
    @Query('limit') limit: string = '10',
  ) {
    return await this.dashboardService.getCompanyJobs(
      parseInt(companyId),
      parseInt(page),
      parseInt(limit),
    );
  }

  @Public()
  @Get('company/:companyId/jobs/:jobId/applicants')
  async getCompanyJobApplicants(
    @Param('companyId') companyId: string,
    @Param('jobId') jobId: string,
    @Query('page') page: string = '1',
    @Query('limit') limit: string = '20',
  ) {
    return await this.dashboardService.getCompanyJobApplicants(
      parseInt(companyId),
      parseInt(jobId),
      parseInt(page),
      parseInt(limit),
    );
  }

  @Public()
  @Get('company/:companyId/credentials')
  async getCompanyCredentials(@Param('companyId') companyId: string) {
    return await this.dashboardService.getCompanyCredentials(
      parseInt(companyId),
    );
  }

  @Public()
  @Put('company/:companyId/update')
  @ApiOperation({ summary: 'Update Company (Franchise Dashboard)' })
  @ApiParam({ name: 'companyId', type: String })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        about: { type: 'string' },
        vision: { type: 'string' },
        founded_at: { type: 'string', format: 'date' },
        location: { type: 'string' },
        website: { type: 'string' },
        industry_id: { type: 'number' },
        organization_type_id: { type: 'number' },
        company_size_id: { type: 'number' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
        pincode: { type: 'string' },
        latitude: { type: 'number' },
        longitude: { type: 'number' },
        email: { type: 'string', description: 'Update recruiter email' },
        phone: { type: 'string', description: 'Update recruiter phone' },
        logo: { type: 'string', description: 'URL' },
        banner_url: { type: 'string', description: 'URL' },
        area_id: { type: 'number' },
        gst_number: { type: 'string' },
        cin_number: { type: 'string' },
        social_links: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              platform_id: { type: 'number' },
              url: { type: 'string' },
            },
          },
        },
      },
    },
  })
  async updateCompany(
    @Param('companyId') companyId: string,
    @Body() updateData: any,
  ) {
    try {
      const result = await this.dashboardService.updateCompany(
        parseInt(companyId),
        updateData,
      );
      return {
        success: true,
        message: 'Company updated successfully',
        data: result,
      };
    } catch (error) {
      console.error('Error updating company (Controller):', error);
      return {
        success: false,
        message: 'Failed to update company',
        error: error.message,
      };
    }
  }

  @Public()
  @Put('company/:companyId/toggle_status')
  async toggleFranchiseCompanyStatus(@Param('companyId') companyId: string) {
    try {
      //console.log('Controller: Toggling status for company ID:', companyId);
      const result = await this.dashboardService.toggleFranchiseCompanyStatus(
        parseInt(companyId),
      );
      //console.log('Controller: Service result:', result);
      return {
        success: true,
        message: result.message,
        data: result.data || result,
      };
    } catch (error) {
      // console.error('Error toggling company status:', error);
      return {
        success: false,
        message: 'Failed to toggle company status',
      };
    }
  }

  @Public()
  @Get('franchise/user/:userId')
  async getFranchiseIdByUserId(@Param('userId') userId: string) {
    const franchiseId = await this.dashboardService.getFranchiseIdByUserId(
      parseInt(userId),
    );
    return {
      success: true,
      data: { franchiseId },
    };
  }

  // Franchise Settings Endpoints
  @Public()
  @Get('franchise/settings')
  async getFranchiseSettings(@Query('userId') userId: number) {
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.getFranchiseSettings(userId);
  }

  @Public()
  @Put('franchise/settings/franchise_info')
  @ApiOperation({ summary: 'Update Franchise Info' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        franchiseName: {
          type: 'string',
          description: 'Updates User Full Name',
        },
        companyName: { type: 'string' },
        email: { type: 'string', format: 'email' },
        contactNo: { type: 'string', description: 'Updates User Phone' },
        address: { type: 'string' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
        postal_code: { type: 'string' },
        area_id: { type: 'number' },
        gstNo: { type: 'string' },
        serviceArea: { type: 'string' },
      },
      required: ['userId'],
    },
  })
  async updateFranchiseInfo(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.updateFranchiseInfo(userId, data);
  }

  @Public()
  @Put('franchise/settings/user_info')
  @ApiOperation({ summary: 'Update Franchise User Info' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        fullName: { type: 'string' },
        phone: { type: 'string' },
        email: { type: 'string', format: 'email' },
      },
      required: ['userId'],
    },
  })
  async updateFranchiseUserInfo(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.updateFranchiseUserInfo(userId, data);
  }

  @Public()
  @Put('franchise/settings/password')
  @ApiOperation({ summary: 'Update Franchise Password' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        newPassword: { type: 'string' },
        confirmPassword: { type: 'string' },
        otp: { type: 'string', description: 'Required if 2FA enabled' },
        requireOTP: { type: 'boolean', default: false },
      },
      required: ['userId', 'newPassword', 'confirmPassword'],
    },
  })
  async updateFranchisePassword(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.updateFranchisePassword(userId, data);
  }

  @Public()
  @Post('franchise/settings/send_otp_password_change')
  async sendOTPForFranchisePasswordChange(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.sendOTPForPasswordChange(userId);
  }

  @Public()
  @Post('franchise/settings/send_otp_contact_info_change')
  async sendOTPForFranchiseContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.sendOTPForContactInfoChange(
      userId,
      changedFields,
    );
  }

  @Public()
  @Post('franchise/settings/verify_otp_contact_info_change')
  async verifyOTPForFranchiseContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const otp = data.otp;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!otp) {
      return { success: false, message: 'otp is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.verifyOTPForContactInfoChange(
      userId,
      otp,
      changedFields,
    );
  }

  @Public()
  @Delete('franchise/settings/account')
  async deleteFranchiseAccount(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.deleteFranchiseAccount(userId);
  }

  @Public()
  @Post('franchise/settings/upload_logo')
  @UseInterceptors(
    FileInterceptor('logo', {
      storage: diskStorage({
        destination: (req, file, cb) => {
          const uploadDir = './uploads/franchise-logos';
          // Create directory if it doesn't exist
          if (!fs.existsSync(uploadDir)) {
            fs.mkdirSync(uploadDir, { recursive: true });
          }
          cb(null, uploadDir);
        },
        filename: (req, file, cb) => {
          const uniqueSuffix =
            Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, uniqueSuffix + extname(file.originalname));
        },
      }),
      limits: { fileSize: 5 * 1024 * 1024 },
      fileFilter: (req, file, cb) => {
        if (!file.originalname.match(/\.(jpg|jpeg|png|gif|webp|avif)$/i)) {
          return cb(
            new Error(
              'Logo must be in JPG, JPEG, PNG, GIF, WebP, or AVIF format',
            ),
            false,
          );
        }
        cb(null, true);
      },
    }),
  )
  async uploadFranchiseLogo(
    @UploadedFile() file: Express.Multer.File,
    @Body('userId') userId: number,
  ) {
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.uploadFranchiseLogo(userId, file);
  }

  @Public()
  @Delete('franchise/settings/delete_logo')
  async deleteFranchiseLogo(@Body('userId') userId: number) {
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.deleteFranchiseLogo(userId);
  }

  @Public()
  @Get('seeker/favorite_jobs/is_job_bookmarked')
  @ApiOperation({ summary: 'Check if Job is Bookmarked' })
  @ApiQuery({ name: 'userId', required: true, type: String })
  @ApiQuery({ name: 'jobPostId', required: true, type: String })
  async isJobBookmarked(
    @Query('userId') userId: string,
    @Query('jobPostId') jobPostId: string,
  ) {
    return this.dashboardService.isJobBookmarked(userId, jobPostId);
  }

  @Post('seeker/upload_resume')
  @Public()
  @ApiOperation({ summary: 'Upload Resume' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        resume: { type: 'string', format: 'binary' },
        seeker_id: { type: 'number' },
        name: { type: 'string' },
      },
      required: ['resume', 'seeker_id'],
    },
  })
  @UseInterceptors(
    FileInterceptor('resume', {
      storage: diskStorage({
        destination: './uploads/resumes',
        filename: (req, file, cb) => {
          const uniqueSuffix =
            Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, uniqueSuffix + extname(file.originalname));
        },
      }),
      limits: { fileSize: 5 * 1024 * 1024 }, // 5MB limit - optimized for mobile uploads
      fileFilter: (req, file, cb) => {
        if (!file.originalname.match(/\.(pdf|doc|docx)$/)) {
          return cb(new Error('Only document files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadResume(
    @UploadedFile() file: Express.Multer.File,
    @Body('seeker_id') seekerId: number,
    @Body('name') name?: string,
    @Req() req?: Request,
  ) {
    try {
      if (!file) {
        throw new HttpException(
          'Resume file is required',
          HttpStatus.BAD_REQUEST,
        );
      }
      if (!seekerId) {
        throw new HttpException(
          'Seeker ID is required',
          HttpStatus.BAD_REQUEST,
        );
      }
      const result = await this.dashboardService.uploadResume(
        seekerId,
        file,
        name,
        req,
      );

      // Log successful upload (non-blocking - fire and forget)
      this.logResumeUploadSuccess(seekerId, file, name, result, req).catch(
        (logError) => {
          console.error('Failed to log successful resume upload:', logError);
        },
      );

      return result;
    } catch (error) {
      // Log detailed error for developers
      const detailedError = {
        errorType: error?.constructor?.name || 'Unknown',
        errorMessage: error?.message || 'Unknown error',
        stack: error instanceof Error ? error.stack : undefined,
        seekerId,
        fileName: file?.originalname,
        fileSize: file?.size,
        name,
        timestamp: new Date().toISOString(),
      };
      console.error('Resume upload error (detailed):', detailedError);

      // Return user-friendly error messages
      if (error instanceof HttpException) {
        // For known errors, return user-friendly message
        const userFriendlyMessage = this.getUserFriendlyMessage(error.message);
        throw new HttpException(userFriendlyMessage, error.getStatus());
      }

      // Check for Multer file size limit error
      if (error instanceof MulterError && error.code === 'LIMIT_FILE_SIZE') {
        // Log file size error (non-blocking)
        this.logResumeUploadError(
          seekerId,
          file,
          name,
          error,
          'FILE_SIZE_EXCEEDED',
          null,
          req,
          HttpStatus.BAD_REQUEST,
        ).catch((logError) => {
          console.error('Failed to log file size error:', logError);
        });

        throw new HttpException(
          'File size exceeds the maximum limit of 5MB. Please upload a smaller file.',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Check for duplicate resume errors with specific codes
      if (error instanceof Error && (error as any).code) {
        const errorCode = (error as any).code;
        if (
          errorCode === 'DUPLICATE_BOTH' ||
          errorCode === 'DUPLICATE_FILENAME' ||
          errorCode === 'DUPLICATE_NAME'
        ) {
          // Log duplicate error (non-blocking)
          this.logResumeUploadError(
            seekerId,
            file,
            name,
            error,
            errorCode,
            (error as any).existingResumeId,
            req,
            HttpStatus.CONFLICT,
          ).catch((logError) => {
            console.error('Failed to log duplicate error:', logError);
          });

          const errorResponse = {
            message: error.message,
            code: errorCode,
            existingResumeId: (error as any).existingResumeId,
          };
          throw new HttpException(errorResponse, HttpStatus.CONFLICT); // 409 Conflict
        }
      }

      // Check for other duplicate resume name errors
      if (error instanceof Error && error.message.includes('already exists')) {
        throw new HttpException(error.message, HttpStatus.BAD_REQUEST);
      }

      // Check for file too large errors (other formats)
      if (
        error instanceof Error &&
        (error.message.includes('File too large') ||
          error.message.includes('LIMIT_FILE_SIZE') ||
          error.message.includes('file size'))
      ) {
        // Log file size error (non-blocking)
        this.logResumeUploadError(
          seekerId,
          file,
          name,
          error,
          'FILE_SIZE_EXCEEDED',
          null,
          req,
          HttpStatus.BAD_REQUEST,
        ).catch((logError) => {
          console.error('Failed to log file size error:', logError);
        });

        throw new HttpException(
          'File size exceeds the maximum limit of 5MB. Please upload a smaller file.',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Check for file type errors
      if (
        error instanceof Error &&
        error.message.includes('Only document files')
      ) {
        // Log file type error (non-blocking)
        this.logResumeUploadError(
          seekerId,
          file,
          name,
          error,
          'INVALID_FILE_TYPE',
          null,
          req,
          HttpStatus.BAD_REQUEST,
        ).catch((logError) => {
          console.error('Failed to log file type error:', logError);
        });

        throw new HttpException(
          'Only PDF, DOC, or DOCX files are allowed',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Log unknown error (non-blocking)
      this.logResumeUploadError(
        seekerId,
        file,
        name,
        error,
        'UNKNOWN_ERROR',
        null,
        req,
        HttpStatus.INTERNAL_SERVER_ERROR,
      ).catch((logError) => {
        console.error('Failed to log unknown error:', logError);
      });

      // For unknown errors, return generic user-friendly message
      throw new HttpException(
        'Failed to upload resume. Please try again later.',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  // Helper method to log successful resume upload (non-blocking)
  private async logResumeUploadSuccess(
    seekerId: number,
    file: Express.Multer.File,
    name: string | undefined,
    result: any,
    req?: Request,
  ): Promise<void> {
    try {
      if (!req) return;

      // Fetch seeker profile to get the correct user_id
      const seekerProfile = await this.seekerProfileRepository.findOne({
        where: { id: seekerId },
      });

      const userId = seekerProfile?.user_id || seekerId;

      const ipAddress =
        (req as any).ip ||
        req.headers['x-forwarded-for'] ||
        (req as any).connection?.remoteAddress;

      await this.activityLogsService.log({
        userId: userId,
        userType: 'seeker',
        actionType: 'seeker_action',
        actionName: 'Resume Uploaded',
        pageUrl: req.url || '/dashboard/seeker/upload_resume',
        actionDetails: {
          fileName: file?.originalname,
          fileSize: file?.size,
          fileType: file?.mimetype,
          resumeName: name || file?.originalname,
          resumeId: result?.resume_id || null,
          action: 'upload_resume',
          status: 'success',
        },
        status: 'success',
        errorMessage: null,
        ipAddress: Array.isArray(ipAddress) ? ipAddress[0] : ipAddress,
        deviceType: 'desktop',
        browser: req.headers['user-agent'] || 'Unknown',
      });
    } catch (error) {
      // Silently fail - logging should not break the app
      console.error('Failed to log successful resume upload:', error);
    }
  }

  // Helper method to log resume upload errors (non-blocking)
  private async logResumeUploadError(
    seekerId: number,
    file: Express.Multer.File | undefined,
    name: string | undefined,
    error: any,
    errorCode: string,
    existingResumeId: number | null,
    req?: Request,
    httpStatus?: number,
  ): Promise<void> {
    try {
      if (!req) return;

      // Fetch seeker profile to get the correct user_id
      const seekerProfile = await this.seekerProfileRepository.findOne({
        where: { id: seekerId },
      });

      const userId = seekerProfile?.user_id || seekerId;

      const ipAddress =
        (req as any).ip ||
        req.headers['x-forwarded-for'] ||
        (req as any).connection?.remoteAddress;

      await this.activityLogsService.log({
        userId: userId,
        userType: 'seeker',
        actionType: 'seeker_action',
        actionName: 'Resume Upload Failed (Server)',
        pageUrl: req.url || '/dashboard/seeker/upload_resume',
        actionDetails: {
          errorType: error?.constructor?.name || 'Unknown',
          errorMessage: error?.message || 'Unknown error',
          errorCode: errorCode,
          existingResumeId: existingResumeId,
          seekerId: seekerId,
          fileName: file?.originalname || null,
          fileSize: file?.size || null,
          name: name || null,
          httpStatus: httpStatus || null,
          stack:
            error instanceof Error ? error.stack?.substring(0, 500) : undefined,
        },
        status: 'failed',
        errorMessage: error?.message || 'Upload failed',
        ipAddress: Array.isArray(ipAddress) ? ipAddress[0] : ipAddress,
        deviceType: 'desktop',
        browser: req.headers['user-agent'] || 'Unknown',
      });
    } catch (logError) {
      // Silently fail - logging should not break the app
      console.error('Failed to log resume upload error:', logError);
    }
  }

  private getUserFriendlyMessage(errorMessage: string): string {
    // Map technical error messages to user-friendly ones
    const errorMap: { [key: string]: string } = {
      'Resume file is required': 'Please select a resume file to upload',
      'Seeker ID is required': 'Invalid request. Please refresh and try again',
      'Failed to save resume':
        'Failed to upload resume. Please try again later',
    };
    return (
      errorMap[errorMessage] ||
      'Failed to upload resume. Please try again later.'
    );
  }
  @Public()
  @Get('seeker/resumes')
  async getSeekerResumes(@Query('user_id') userId: number) {
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.getSeekerResumesByUserId(userId);
  }

  @Public()
  @Get('validate-cv/:seekerId')
  async validateCV(@Param('seekerId') seekerId: string) {
    try {
      const result = await this.dashboardService.validateSeekerCV(
        parseInt(seekerId),
      );

      if (!result.success) {
        throw new HttpException(
          { success: false, message: result.error || 'CV not found' },
          HttpStatus.NOT_FOUND,
        );
      }

      return {
        success: true,
        message: 'CV is available',
        data: {
          filename: result.data.filename,
          exists: true,
        },
      };
    } catch (error: any) {
      throw new HttpException(
        { success: false, message: error.message || 'Error validating CV' },
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('download-cv/:seekerId')
  async downloadCV(@Param('seekerId') seekerId: string, @Res() res: Response) {
    try {
      const result = await this.dashboardService.downloadSeekerCV(
        parseInt(seekerId),
      );

      if (!result.success) {
        throw new HttpException(
          result.error || 'CV not found',
          HttpStatus.NOT_FOUND,
        );
      }

      // Set headers for file download
      res.setHeader('Content-Type', result.data.contentType);
      res.setHeader(
        'Content-Disposition',
        `attachment; filename="${result.data.filename}"`,
      );
      res.setHeader('Content-Length', result.data.fileBuffer.length);

      // Send the file
      res.send(result.data.fileBuffer);
    } catch (error: any) {
      throw new HttpException(
        error.message || 'Error downloading CV',
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Put('seeker/profile/:profileId')
  @ApiOperation({ summary: 'Update Seeker Basic Info' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        full_name: { type: 'string' },
        phone: { type: 'string' },
        job_title: { type: 'string' },
        about: { type: 'string' },
        experience_years: { type: 'number' },
        current_salary: { type: 'number' },
        expected_salary: { type: 'number' },
        location: { type: 'string' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
        availability: { type: 'string' },
        biography: { type: 'string' },
      },
    },
  })
  async updateSeekerProfileBasicInfo(
    @Param('profileId') userId: number,
    @Body() body: any,
  ) {
    //console.log('Updating profile for userId:', userId);
    //console.log('Received data:', body);
    return this.dashboardService.updateSeekerProfileBasicInfo(userId, body);
  }
  @Public()
  @Get('seeker/profile')
  async getSeekerProfileByUserId(@Query('user_id') userId: number) {
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.getSeekerProfileByUserId(userId);
  }
  // @Public()
  // @Get('seeker/seeker_id')
  // async getSeekerProfile(@Query('user_id') userId: number) {
  //   if (!userId) {
  //     return { success: false, message: 'user_id is required' };
  //   }
  //   return await this.dashboardService.getSeekerIdByUserId(userId);
  // }
  @Public()
  @Get('seeker/seeker_id')
  async getSeekerProfile(@Query('user_id') userId: number) {
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    const seekerId = await this.dashboardService.getSeekerIdByUserId(userId);
    if (seekerId !== null && seekerId !== undefined) {
      return { success: true, seeker_id: seekerId };
    }
    return { success: false, message: 'Seeker profile not found' };
  }

  @Public()
  @Get('seeker/full_profile')
  async getSeekerFullProfile(@Query('userId') userId: number) {
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.getSeekerFullProfile(userId);
  }

  // @Public()
  // @Post('seeker/job-alerts')
  // async createJobAlert(@Request() req, @Body() createJobAlertData: any) {
  //   const userId = req.user?.id || req.body?.userId;
  //   return await this.dashboardService.createJobAlert(
  //     userId,
  //     createJobAlertData,
  //   );
  // }
  @Public()
  @Get('seeker/job_alerts')
  async getSeekerJobAlerts(@Query('userId') userId: number, @Query() query) {
    const page = query.page ? Number(query.page) : 1;
    const limit = query.limit ? Number(query.limit) : 10;
    return await this.dashboardService.getSeekerJobAlerts(userId, {
      page,
      limit,
    });
  }
  @Public()
  @Get('seeker/alert_jobs/list')
  async getSeekeralertJobsList(
    @Query('userId') userId: number,
    @Query() query,
  ) {
    const page = query.page ? Number(query.page) : 1;
    const limit = query.limit ? Number(query.limit) : 10;
    return await this.dashboardService.getJobAlertsjoblistForSeeker(userId, {
      page,
      limit,
    });
  }
  @Public()
  @Post('job_alerts/auto_create/:jobPostId')
  async createJobAlertsForNewPost(@Param('jobPostId') jobPostId: number) {
    await this.dashboardService.createJobAlertsForNewPost(Number(jobPostId));
    return { success: true, message: 'Job alerts created for new job post' };
  }

  @Public()
  @Delete('seeker/job_alerts/:alertId')
  async deleteJobAlert(@Request() req, @Param('alertId') alertId: string) {
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.deleteJobAlert(userId, alertId);
  }

  @Public()
  @Delete('seeker/resumes/:resumeId')
  async softDeleteSeekerResume(
    @Request() req,
    @Param('resumeId') resumeId: number,
    @Query('user_id') userIdFromQuery: number,
  ) {
    const userId = userIdFromQuery || req.user?.id || req.body?.userId;
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.softDeleteSeekerResume(
      Number(userId),
      Number(resumeId),
    );
  }
  //---seeker skills CRUD
  @Public()
  @Get('seeker/skills')
  async getSeekerSkills(@Query('seeker_id') seeker_id: number) {
    const skills = await this.dashboardService.getSeekerSkills(seeker_id);
    return { success: true, skills };
  }
  //---seeker languages CRUD
  @Public()
  @Get('seeker/languages')
  async getSeekerLanguages(@Query('seeker_id') seeker_id: number) {
    const languages = await this.dashboardService.getSeekerLanguages(seeker_id);
    return { success: true, languages };
  }
  // --- Seeker Experiences CRUD ---
  @Public()
  @Get('seeker/experiences')
  async getSeekerExperiences(@Query('seeker_id') seeker_id: number) {
    const experiences =
      await this.dashboardService.getSeekerExperiences(seeker_id);
    return { success: true, experiences };
  }

  @Public()
  @Post('seeker/experiences')
  @ApiOperation({ summary: 'Add Seeker Experience' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        seeker_id: { type: 'number' },
        job_title: { type: 'string' },
        company_name: { type: 'string' },
        start_date: { type: 'string', format: 'date' },
        end_date: { type: 'string', format: 'date' },
        is_current: { type: 'boolean' },
        description: { type: 'string' },
        location: { type: 'string' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
      },
      required: [
        'seeker_id',
        'job_title',
        'company_name',
        'start_date',
        'is_current',
      ],
    },
  })
  async addSeekerExperience(@Body() data: any) {
    // console.log('Received experience data (POST):', data);
    const experience = await this.dashboardService.addSeekerExperience(data);
    return { success: true, experience };
  }

  @Public()
  @Put('seeker/experiences/:id')
  @ApiOperation({ summary: 'Update Seeker Experience' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        job_title: { type: 'string' },
        company_name: { type: 'string' },
        start_date: { type: 'string', format: 'date' },
        end_date: { type: 'string', format: 'date' },
        is_current: { type: 'boolean' },
        description: { type: 'string' },
        location: { type: 'string' },
        country_id: { type: 'number' },
        state_id: { type: 'number' },
        city_id: { type: 'number' },
      },
    },
  })
  async updateSeekerExperience(@Param('id') id: number, @Body() data: any) {
    // console.log(
    //   'Received experience data (PUT):',
    //   data,
    //   'current:',
    //   data.current,
    // );
    const experience = await this.dashboardService.updateSeekerExperience(
      id,
      data,
    );
    return { success: true, experience };
  }

  @Public()
  @Delete('seeker/experiences/:id')
  async deleteSeekerExperience(@Param('id') id: number) {
    await this.dashboardService.deleteSeekerExperience(id);
    return { success: true };
  }

  // --- Seeker Educations CRUD ---
  @Public()
  @Get('seeker/educations')
  async getSeekerEducations(@Query('seeker_id') seeker_id: number) {
    const educations =
      await this.dashboardService.getSeekerEducations(seeker_id);
    return { success: true, educations };
  }

  @Public()
  @Post('seeker/educations')
  @ApiOperation({ summary: 'Add Seeker Education' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        seeker_id: { type: 'number' },
        education_level_id: {
          type: 'number',
          description: 'Education level ID',
        },
        degree: { type: 'string', description: 'Degree name' },
        year: { type: 'number', description: 'Year of completion' },
        notes: { type: 'string', description: 'Additional notes' },
      },
      required: ['seeker_id', 'education_level_id', 'degree'],
    },
  })
  async addSeekerEducation(@Body() data: any) {
    const education = await this.dashboardService.addSeekerEducation(data);
    return { success: true, education };
  }

  @Public()
  @Put('seeker/educations/:id')
  @ApiOperation({ summary: 'Update Seeker Education' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        education_level_id: {
          type: 'number',
          description: 'Education level ID',
        },
        degree: { type: 'string', description: 'Degree name' },
        year: { type: 'number', description: 'Year of completion' },
        notes: { type: 'string', description: 'Additional notes' },
      },
    },
  })
  async updateSeekerEducation(@Param('id') id: number, @Body() data: any) {
    const education = await this.dashboardService.updateSeekerEducation(
      id,
      data,
    );
    return { success: true, education };
  }

  @Public()
  @Delete('seeker/educations/:id')
  async deleteSeekerEducation(@Param('id') id: number) {
    await this.dashboardService.deleteSeekerEducation(id);
    return { success: true };
  }

  // --- Social Platform CRUD ---
  @Public()
  @Get('social_platforms')
  async getSocialPlatforms() {
    return await this.dashboardService.getSocialPlatforms();
  }
  @Public()
  @Get('seeker/social_links')
  async getSeekerSocialLinks(@Query('seeker_id') seeker_id: number) {
    const socialLinks =
      await this.dashboardService.getSeekerSocialLinks(seeker_id);
    // console.log('Social links:', socialLinks);
    return { success: true, socialLinks };
  }
  @Public()
  @Post('seeker/social_links')
  @ApiOperation({ summary: 'Add Seeker Social Link' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        seeker_id: { type: 'number' },
        platform_id: { type: 'number' },
        url: { type: 'string' },
      },
      required: ['seeker_id', 'url'],
    },
  })
  async addSeekerSocialLink(@Body() data: any) {
    // console.log('Received social link data (POST):', data);
    const link = await this.dashboardService.addSeekerSocialLink(data);
    return { success: true, link };
  }
  @Public()
  @Put('seeker/social_links/:id')
  @ApiOperation({ summary: 'Update Seeker Social Link' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        platform_id: { type: 'number' },
        url: { type: 'string' },
      },
    },
  })
  async updateSeekerSocialLink(@Param('id') id: number, @Body() data: any) {
    const link = await this.dashboardService.updateSeekerSocialLink(id, data);
    return { success: true, link };
  }
  @Public()
  @Delete('seeker/social_links/:id')
  async deleteSeekerSocialLink(@Param('id') id: number) {
    await this.dashboardService.deleteSeekerSocialLink(id);
    return { success: true };
  }

  // ---address CRUD ---

  @Public()
  @Get('locations')
  async getLocations(@Query('status') status?: any) {
    const s =
      status !== undefined && !isNaN(Number(status))
        ? Number(status)
        : undefined;
    return await this.dashboardService.getLocations(s);
  }
  @Public()
  @Get('IndustriesRoleLevelRole')
  async getIndustriesRoleLevelRole() {
    return await this.dashboardService.getIndustriesRoleLevelRole();
  }
  @Public()
  @Get('seeker/address')
  async getSeekerAddress(
    @Query('seeker_profile_id') seeker_profile_id: number,
  ) {
    return await this.dashboardService.getSeekerAddress(seeker_profile_id);
  }
  @Public()
  @Post('seeker/address')
  async addSeekerAddress(@Body() data: any) {
    return await this.dashboardService.addSeekerAddress(data);
  }
  @Public()
  @Put('seeker/address/:id')
  async updateSeekerAddress(@Param('id') id: number, @Body() data: any) {
    return await this.dashboardService.updateSeekerAddress(id, data);
  }
  @Public()
  @Delete('seeker/address/:id')
  async deleteSeekerAddress(@Param('id') id: number) {
    await this.dashboardService.deleteSeekerAddress(id);
    return { success: true };
  }
  @Public()
  @Put('seeker/contact_info')
  async updateUserContactInfo(@Request() req, @Body() data: any) {
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.updateUserContactInfo(userId, data);
  }
  @Public()
  @Get('seeker/contact_info')
  async getUserContactInfo(@Query('userId') userId: number) {
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.getUserContactInfo(userId);
  }
  @Public()
  @Put('seeker/password')
  async updateUserPassword(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.updateUserPassword(userId, data);
  }

  @Public()
  @Post('seeker/send_otp_password_change')
  async sendOTPForSeekerPasswordChange(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'user_id is required' };
    }
    return await this.dashboardService.sendOTPForPasswordChange(userId);
  }

  @Public()
  @Post('seeker/send_otp_contact_info_change')
  async sendOTPForSeekerContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.sendOTPForContactInfoChange(
      userId,
      changedFields,
    );
  }

  @Public()
  @Post('seeker/verify_otp_contact_info_change')
  async verifyOTPForSeekerContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const otp = data.otp;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!otp) {
      return { success: false, message: 'otp is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.verifyOTPForContactInfoChange(
      userId,
      otp,
      changedFields,
    );
  }
  @Public()
  // COMMENTED OUT: Inactive account functionality
  // @Put('seeker/inactive')
  // async updateSeekerUserInactive(@Body() data: any) {
  //   const userId = data.userId;
  //   if (!userId) {
  //     return { success: false, message: 'user_id is required' };
  //   }
  //   return await this.dashboardService.updateSeekerUserInactive(userId);
  // }
  //---check if seeker apply job status like applied, shortlisted, rejected, pending, etc.
  @Public()
  @Get('seeker/applied_job_status')
  async checkIfSeekerAppliedForJob(
    @Query('userId') userId: number,
    @Query('jobPostId') jobPostId: number,
  ) {
    // console.log('checkIfSeekerAppliedForJob', userId, jobPostId);
    return await this.dashboardService.checkIfSeekerAppliedForJob(
      userId,
      jobPostId,
    );
  }
  // Recruiter Dashboard Endpoints
  @Public()
  @Get('recruiter/overview')
  async getRecruiterOverview(@Request() req, @Query('userId') userId?: string) {
    const userIdFromRequest = req.user?.id || req.body?.userId || userId;
    return await this.dashboardService.getRecruiterOverview(userIdFromRequest);
  }

  @Public()
  @Get('recruiter/ai_jobs/:jobId/applicants')
  async getRecruiterAiJobApplicants(
    @Request() req,
    @Param('jobId') jobId: string,
    @Query() query,
  ) {
    const userId = req.user?.id || query.userId;
    const { page = 1, limit = 10 } = query;
    return await this.dashboardService.getRecruiterAiJobApplicants(
      userId,
      Number(jobId),
      {
        page: Number(page),
        limit: Number(limit),
      },
    );
  }
  @Public()
  @Get('recruiter/ai_jobs/interview/:interviewId')
  async getRecruiterAiInterviewDetails(
    @Request() req,
    @Param('interviewId') interviewId: string,
    @Query() query,
  ) {
    const userId = req.user?.id || query.userId;
    return await this.dashboardService.getRecruiterAiInterviewDetails(
      userId,
      Number(interviewId),
    );
  }
  @Public()
  @Get('recruiter/ai_jobs')
  async getRecruiterAiJobs(@Request() req, @Query() query) {
    const userId = req.user?.id || query.userId;
    const { page = 1, limit = 10, search } = query;
    return await this.dashboardService.getRecruiterAiJobs(userId, {
      page: Number(page),
      limit: Number(limit),
      search,
    });
  }
  @Public()
  @Get('recruiter/posted_jobs')
  async getRecruiterPostedJobs(@Request() req, @Query() query) {
    const userId = req.user?.id || query.userId; // FIX: Get userId from query params for GET request
    const { page = 1, limit = 10, status, search, hasApplications } = query;
    return await this.dashboardService.getRecruiterPostedJobsWithApplications(
      userId,
      {
        page,
        limit,
        status,
        search,
        hasApplications: hasApplications === 'true' || hasApplications === true,
      },
    );
  }

  @Public()
  @Get('recruiter/posted_jobs_with_applications')
  async getRecruiterPostedJobsWithApplications(@Request() req, @Query() query) {
    const userId = req.user?.id || query.userId; // FIX: Get userId from query params for GET request
    const { page = 1, limit = 10, status } = query;
    return await this.dashboardService.getRecruiterPostedJobsWithApplications(
      userId,
      {
        page,
        limit,
        status,
      },
    );
  }

  @Public()
  @Get('recruiter/applications')
  async getRecruiterApplications(@Request() req, @Query() query) {
    const userId = req.user?.id || query.userId; // FIX: Get userId from query params for GET request
    const { page = 1, limit = 10, status, jobId } = query;
    return await this.dashboardService.getRecruiterApplications(userId, {
      page,
      limit,
      status,
      jobId,
    });
  }

  @Public()
  @Put('recruiter/applications/:applicationId/status')
  @ApiOperation({ summary: 'Update Application Status' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'string' },
        status: {
          type: 'string',
          enum: ['shortlisted', 'rejected', 'interview', 'hired'],
        },
      },
      required: ['userId', 'status'],
    },
  })
  async updateApplicationStatus(
    @Request() req,
    @Param('applicationId') applicationId: string,
    @Body() updateStatusData: { userId: string; status: string },
  ) {
    const userId = updateStatusData.userId;
    return await this.dashboardService.updateApplicationStatus(
      userId,
      applicationId,
      updateStatusData.status,
    );
  }

  @Public()
  @Get('recruiter/messages')
  async getRecruiterMessages(@Request() req, @Query() query) {
    const userId = req.user?.id || req.body?.userId;
    const { page = 1, limit = 10 } = query;
    return await this.dashboardService.getRecruiterMessages(userId, {
      page,
      limit,
    });
  }

  @Public()
  @Post('recruiter/messages')
  @ApiOperation({ summary: 'Send Message' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'string' },
        receiverId: { type: 'string' },
        jobId: { type: 'string' },
        message: { type: 'string' },
      },
      required: ['userId', 'receiverId', 'message'],
    },
  })
  async sendMessage(@Request() req, @Body() sendMessageData: any) {
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.sendMessage(userId, sendMessageData);
  }

  @Public()
  @Get('recruiter/saved_candidates')
  async getSavedCandidates(@Request() req, @Query() query) {
    const userId = req.user?.id || query.userId;
    const { page = 1, limit = 10 } = query;
    return await this.dashboardService.getSavedCandidates(userId, {
      page,
      limit,
    });
  }

  @Public()
  @Post('recruiter/saved_candidates')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'string' },
        candidateId: { type: 'string' },
      },
      required: ['userId', 'candidateId'],
    },
  })
  async saveCandidate(
    @Request() req,
    @Body() saveCandidateData: { userId: string; candidateId: string },
  ) {
    const userId = req.user?.id || saveCandidateData.userId;
    return await this.dashboardService.saveCandidate(
      userId,
      saveCandidateData.candidateId,
    );
  }

  @Public()
  @Delete('recruiter/saved_candidates/:candidateId')
  async removeSavedCandidate(
    @Request() req,
    @Param('candidateId') candidateId: string,
    @Body() removeData: { userId: string },
  ) {
    const userId = req.user?.id || removeData?.userId;
    return await this.dashboardService.removeSavedCandidate(
      userId,
      candidateId,
    );
  }

  @Public()
  @Get('recruiter/saved_candidates/check/:candidateId')
  async isCandidateSaved(
    @Request() req,
    @Param('candidateId') candidateId: string,
  ) {
    const userId = req.user?.id || req.query?.userId;
    return await this.dashboardService.isCandidateSaved(userId, candidateId);
  }

  // Analytics Endpoints
  @Public()
  @Get('analytics/job_views')
  async getJobViews(@Request() req, @Query() query) {
    const userId = req.user?.id || req.body?.userId;
    const { jobId, period = '30d' } = query;
    return await this.dashboardService.getJobViews(userId, jobId, period);
  }

  @Public()
  @Get('analytics/application_stats')
  async getApplicationStats(@Request() req, @Query() query) {
    const userId = req.user?.id || req.body?.userId;
    const { period = '30d' } = query;
    return await this.dashboardService.getApplicationStats(userId, period);
  }

  @Public()
  @Get('analytics/candidate_stats')
  async getCandidateStats(@Request() req, @Query() query) {
    const userId = req.user?.id || req.body?.userId;
    const { period = '30d' } = query;
    return await this.dashboardService.getCandidateStats(userId, period);
  }

  // Job Management Actions
  @Public()
  @Post('recruiter/jobs/:jobId/promote')
  async promoteJob(@Request() req, @Param('jobId') jobId: string) {
    //console.log('Promoting job with ID:', jobId);
    //console.log('User ID from request:', req.user?.id || req.body?.userId);
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.promoteJob(userId, jobId);
  }

  @Public()
  @Post('recruiter/jobs/:jobId/clone')
  async cloneJob(@Request() req, @Param('jobId') jobId: string) {
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.cloneJob(userId, jobId);
  }

  @Public()
  @Post('recruiter/jobs/:jobId/expire')
  async expireJob(@Request() req, @Param('jobId') jobId: string) {
    const userId = req.user?.id || req.body?.userId;
    return await this.dashboardService.expireJob(userId, jobId);
  }

  // Recruiter Settings Endpoints
  @Public()
  @Get('recruiter/settings')
  async getCompanySettings(@Query('userId') userId: number) {
    // console.log('Fetching company settings for userId:', userId);
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.getCompanySettings(userId);
  }

  @Public()
  @Put('recruiter/settings/company_info')
  async updateCompanyBasicInfo(@Body() data: any) {
    // console.log('=== Backend Controller Debug ===');
    // console.log('Received data:', data);

    const userId = data.userId;
    if (!userId) {
      // console.log('Error: userId is missing');
      return { success: false, message: 'userId is required' };
    }

    // console.log('User ID:', userId);
    // console.log('Data to be processed:', data);

    const result = await this.dashboardService.updateCompanyBasicInfo(
      userId,
      data,
    );
    // console.log('Service result:', result);
    return result;
  }
  //---company social links CRUD---
  @Public()
  @Put('recruiter/settings/social_links')
  async updateCompanySocialLinks(@Body() data: any) {
    // console.log('=== Backend Controller Social Links Debug ===');
    // console.log('Received data:', data);

    const userId = data.userId;
    if (!userId) {
      // console.log('Error: userId is missing');
      return { success: false, message: 'userId is required' };
    }

    // console.log('User ID:', userId);
    // console.log('Social links to process:', data.socialLinks);

    const result = await this.dashboardService.updateCompanySocialLinks(
      userId,
      data.socialLinks,
    );
    // console.log('Service result:', result);
    return result;
  }

  // @Public()
  // @Get('recruiter/social-links/:userId')
  // async getCompanySocialLinks(@Param('userId') userId: string) {
  //   if (!userId) {
  //     return { success: false, message: 'userId is required' };
  //   }
  //   return await this.dashboardService.getCompanySocialLinks(Number(userId));
  // }

  // @Public()
  // @Get('recruiter/social-links')
  // async getCompanySocialLinksByCompanyId(
  //   @Query('company_id') companyId: string,
  // ) {
  //   if (!companyId) {
  //     return { success: false, message: 'company_id is required' };
  //   }
  //   return await this.dashboardService.getCompanySocialLinksByCompanyId(
  //     Number(companyId),
  //   );
  // }

  // Company Social Links endpoints (alternative path for frontend compatibility)
  @Public()
  @Get('company/social_links')
  async getCompanySocialLinksByCompanyIdAlt(
    @Query('company_id') companyId: string,
  ) {
    if (!companyId) {
      return { success: false, message: 'company_id is required' };
    }
    return await this.dashboardService.getCompanySocialLinksByCompanyId(
      Number(companyId),
    );
  }

  @Public()
  @Post('company/social_links')
  async createCompanySocialLinkAlt(@Body() data: any) {
    if (!data.company_id || !data.platform_id || !data.url) {
      return {
        success: false,
        message: 'company_id, platform_id, and url are required',
      };
    }
    return await this.dashboardService.createCompanySocialLink(data);
  }

  @Public()
  @Put('company/social_links/:linkId')
  async updateCompanySocialLinkAlt(
    @Param('linkId') linkId: string,
    @Body() data: any,
  ) {
    if (!linkId) {
      return { success: false, message: 'linkId is required' };
    }
    if (!data.platform_id || !data.url) {
      return { success: false, message: 'platform_id and url are required' };
    }
    return await this.dashboardService.updateCompanySocialLink(
      Number(linkId),
      data,
    );
  }

  @Public()
  @Delete('company/social_links/:linkId')
  async deleteCompanySocialLinkAlt(@Param('linkId') linkId: string) {
    if (!linkId) {
      return { success: false, message: 'linkId is required' };
    }
    return await this.dashboardService.deleteCompanySocialLink(Number(linkId));
  }

  // @Public()
  // @Post('recruiter/social-links')
  // async createCompanySocialLink(@Body() data: any) {
  //   if (!data.company_id || !data.platform_id || !data.url) {
  //     return {
  //       success: false,
  //       message: 'company_id, platform_id, and url are required',
  //     };
  //   }
  //   return await this.dashboardService.createCompanySocialLink(data);
  // }

  // @Public()
  // @Put('recruiter/social-links/:linkId')
  // async updateCompanySocialLink(
  //   @Param('linkId') linkId: string,
  //   @Body() data: any,
  // ) {
  //   if (!linkId) {
  //     return { success: false, message: 'linkId is required' };
  //   }
  //   if (!data.platform_id || !data.url) {
  //     return { success: false, message: 'platform_id and url are required' };
  //   }
  //   return await this.dashboardService.updateCompanySocialLink(
  //     Number(linkId),
  //     data,
  //   );
  // }

  // @Public()
  // @Delete('recruiter/social-links/:linkId')
  // async deleteCompanySocialLink(@Param('linkId') linkId: string) {
  //   if (!linkId) {
  //     return { success: false, message: 'linkId is required' };
  //   }
  //   return await this.dashboardService.deleteCompanySocialLink(Number(linkId));
  // }

  @Public()
  @Put('recruiter/settings/contact_info')
  async updateRecruiterContactInfo(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.updateRecruiterContactInfo(userId, data);
  }

  @Public()
  @Put('recruiter/settings/password')
  async updateRecruiterPassword(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.updateRecruiterPassword(userId, data);
  }

  @Public()
  @Post('recruiter/settings/send_otp_password_change')
  async sendOTPForRecruiterPasswordChange(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.sendOTPForPasswordChange(userId);
  }

  @Public()
  @Post('recruiter/settings/send_otp_contact_info_change')
  async sendOTPForRecruiterContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.sendOTPForContactInfoChange(
      userId,
      changedFields,
    );
  }

  @Public()
  @Post('recruiter/settings/verify_otp_contact_info_change')
  async verifyOTPForRecruiterContactInfoChange(@Body() data: any) {
    const userId = data.userId;
    const otp = data.otp;
    const changedFields = data.changedFields;

    if (!userId) {
      return { success: false, message: 'userId is required' };
    }

    if (!otp) {
      return { success: false, message: 'otp is required' };
    }

    if (!changedFields || (!changedFields.phone && !changedFields.email)) {
      return {
        success: false,
        message: 'changedFields with phone or email is required',
      };
    }

    return await this.dashboardService.verifyOTPForContactInfoChange(
      userId,
      otp,
      changedFields,
    );
  }

  @Public()
  @Delete('recruiter/settings/account')
  async deleteCompanyAccount(@Body() data: any) {
    // console.log('company data', data);
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.deleteCompanyAccount(userId);
  }

  @Public()
  @Get('recruiter/settings/organization_types')
  async getOrganizationTypes() {
    return await this.dashboardService.getOrganizationTypes();
  }

  @Public()
  @Get('recruiter/settings/company_sizes')
  async getCompanySizes() {
    return await this.dashboardService.getCompanySizes();
  }

  @Public()
  @Get('recruiter/settings/industries')
  async getIndustries() {
    return await this.dashboardService.getIndustries();
  }

  @Public()
  @Get('recruiter/settings/social_platforms')
  async getCompanySocialPlatforms() {
    return await this.dashboardService.getCompanySocialPlatforms();
  }

  @Public()
  @Post('recruiter/settings/upload_logo')
  @UseInterceptors(FileInterceptor('logo', { dest: 'uploads/company-logos' }))
  async uploadCompanyLogo(
    @UploadedFile() file: Express.Multer.File,
    @Body('userId') userId: number,
  ) {
    console.log(
      '[Controller] recruiter uploadCompanyLogo received file:',
      file?.originalname,
    );
    if (!userId) return { success: false, message: 'userId is required' };
    return await this.dashboardService.uploadCompanyLogo(userId, file);
  }

  @Public()
  @Post('recruiter/settings/upload_banner')
  @UseInterceptors(
    FileInterceptor('banner', { dest: 'uploads/company-banners' }),
  )
  async uploadCompanyBanner(
    @UploadedFile() file: Express.Multer.File,
    @Body('userId') userId: number,
  ) {
    console.log(
      '[Controller] recruiter uploadCompanyBanner received file:',
      file?.originalname,
    );
    if (!userId) return { success: false, message: 'userId is required' };
    return await this.dashboardService.uploadCompanyBanner(userId, file);
  }

  //add jv companies logo
  @Public()
  @Post('admin_upload_logo')
  @UseInterceptors(FileInterceptor('logo', { dest: 'uploads/company-logos' }))
  async uploadLogoFile(@UploadedFile() file: Express.Multer.File) {
    console.log(
      '[Controller] admin_upload_logo received file:',
      file?.originalname,
    );
    try {
      if (!file) return { success: false, message: 'No file uploaded' };
      return await this.dashboardService.uploadLogoFile(file);
    } catch (error) {
      console.error('Error in uploadLogoFile:', error);
      return {
        success: false,
        message: 'Logo upload failed',
        error: error.message,
      };
    }
  }

  @Public()
  @Post('recruiter/settings/upload_banner_file')
  @UseInterceptors(
    FileInterceptor('banner', { dest: 'uploads/company-banners' }),
  )
  async uploadBannerFile(@UploadedFile() file: Express.Multer.File) {
    console.log(
      '[Controller] uploadBannerFile received file:',
      file?.originalname,
    );
    try {
      if (!file) return { success: false, message: 'No file uploaded' };
      return await this.dashboardService.uploadBannerFile(file);
    } catch (error) {
      console.error('Error in uploadBannerFile:', error);
      return {
        success: false,
        message: 'Banner upload failed',
        error: error.message,
      };
    }
  }

  // Delete company logo
  @Public()
  @Delete('recruiter/settings/delete_logo')
  async deleteCompanyLogo(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.deleteCompanyLogo(userId);
  }

  // Delete company banner
  @Public()
  @Delete('recruiter/settings/delete_banner')
  async deleteCompanyBanner(@Body() data: any) {
    const userId = data.userId;
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.deleteCompanyBanner(userId);
  }

  // Location CRUD Endpoints
  @Public()
  @Get('locations/countries')
  async getCountries() {
    return await this.dashboardService.getCountries();
  }

  // @Public()
  // @Get('locations/states/:countryId')
  // async getStatesByCountry(@Param('countryId') countryId: number) {
  //   return await this.dashboardService.getStatesByCountry(countryId);
  // }

  // @Public()
  // @Get('locations/cities/:stateId')
  // async getCitiesByState(@Param('stateId') stateId: number) {
  //   return await this.dashboardService.getCitiesByState(stateId);
  // }

  // @Public()
  // @Post('locations/countries')
  // async insertCountry(@Body() data: any) {
  //   if (!data.country_name || !data.country_code) {
  //     return {
  //       success: false,
  //       message: 'country_name and country_code are required',
  //     };
  //   }
  //   return await this.dashboardService.insertCountry(data);
  // }

  // @Public()
  // @Post('locations/states')
  // async insertState(@Body() data: any) {
  //   if (!data.state_name || !data.country_id) {
  //     return {
  //       success: false,
  //       message: 'state_name and country_id are required',
  //     };
  //   }
  //   return await this.dashboardService.insertState(data);
  // }

  // @Public()
  // @Post('locations/cities')
  // async insertCity(@Body() data: any) {
  //   if (!data.city_name || !data.state_id) {
  //     return { success: false, message: 'city_name and state_id are required' };
  //   }
  //   return await this.dashboardService.insertCity(data);
  // }

  // Profile Completion Endpoints
  @Public()
  @Get('seeker/profile_completion')
  async getSeekerProfileCompletion(@Query('userId') userId: number) {
    //console.log('Fetching seeker profile completion for userId:', userId);
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.getSeekerProfileCompletion(userId);
  }

  @Public()
  @Get('recruiter/profile_completion')
  async getRecruiterProfileCompletion(@Query('userId') userId: number) {
    //console.log('Fetching recruiter profile completion for userId:', userId);
    if (!userId) {
      return { success: false, message: 'userId is required' };
    }
    return await this.dashboardService.getRecruiterProfileCompletion(userId);
  }
  // @Public()
  // @Get('admin/overview')
  // async getAdminOverview() {
  //   return await this.dashboardService.getAdminOverview();
  // }
  @Public()
  @Get('admin/overview')
  async getAdminOverview(
    @Query('from') from?: string,
    @Query('to') to?: string,
  ) {
    return await this.dashboardService.getAdminOverview(from, to);
  }
  //contaac us form email api
  @Public()
  @Post('contact_form')
  async handleContactForm(
    @Body()
    contactData: {
      name: string;
      email: string;
      subject: string;
      category: string;
      message: string;
    },
  ) {
    try {
      // Validate required fields
      if (
        !contactData.name ||
        !contactData.email ||
        !contactData.subject ||
        !contactData.message
      ) {
        return {
          success: false,
          message: 'All required fields must be provided',
        };
      }

      const toEmail = 'support@jobvumi.com';
      const templateName = 'contact_form';
      
      const context = {
        name: contactData.name,
        email: contactData.email,
        subject: contactData.subject,
        category: contactData.category,
        message_html: contactData.message.replace(/\n/g, '<br>'),
      };

      const success = await this.emailService.sendTemplateEmail(
        templateName,
        toEmail,
        'Support Team',
        context
      );

      if (success) {
        return {
          success: true,
          message:
            'Your message has been sent successfully. We will get back to you soon!',
        };
      } else {
        return {
          success: false,
          message: 'Failed to send message. Please try again later.',
        };
      }
    } catch (error) {
      console.error('Error handling contact form:', error);
      return {
        success: false,
        message:
          'An error occurred while sending your message. Please try again later.',
      };
    }
  }

  @Public()
  @Post('send_credentials_email')
  async sendCredentialsEmail(
    @Body()
    emailData: {
      to: string;
      subject: string;
      message: string;
      accountType?: string; // 'franchise' or 'recruiter'
      credentials: {
        username: string;
        email: string;
        password: string;
        companyName: string;
      };
    },
  ) {
    try {
      const accountType = emailData.accountType || 'recruiter';
      const isFranchise = accountType.toLowerCase() === 'franchise';
      const accountTypeText = isFranchise ? 'Franchise' : 'Recruiter';
      const accountTypeColor = isFranchise ? '#059669' : '#2563eb'; // Green for franchise, Blue for recruiter
      const accountTypeGradientEnd = isFranchise ? '#10b981' : '#4f46e5';
      const accountTypeIcon = isFranchise ? '🏢' : '👤';
      
      const templateName = 'send_credentials';
      const toName = emailData.to.split('@')[0];
      const context = {
        account_type_text: accountTypeText,
        account_type_color: accountTypeColor,
        account_type_gradient_end: accountTypeGradientEnd,
        account_type_icon: accountTypeIcon,
        intro_message: emailData.message || `Here are your ${accountTypeText.toLowerCase()} login credentials for Jobvumi:`,
        company_name: emailData.credentials.companyName,
        username: emailData.credentials.username,
        email: emailData.credentials.email,
        password: emailData.credentials.password,
      };

      const success = await this.emailService.sendTemplateEmail(
        templateName,
        emailData.to,
        toName,
        context
      );

      if (success) {
        return {
          success: true,
          message: 'Credentials sent successfully',
        };
      } else {
        return {
          success: false,
          message: 'Failed to send credentials email',
        };
      }
    } catch (error) {
      console.error('Error sending credentials email:', error);
      return {
        success: false,
        message: 'Failed to send credentials email',
      };
    }
  }

  // // Admin Analytics Endpoints (aggregate across all franchises)
  // @Public()
  // @Get('analytics/overview')
  // async getAdminAnalyticsOverview(@Query('dateRange') dateRange: number = 30) {
  //   try {
  //     const [
  //       jobAnalytics,
  //       applicationAnalytics,
  //       companyAnalytics,
  //       userAnalytics,
  //       franchiseData,
  //     ] = await Promise.all([
  //       this.analyticsService.getJobAnalytics(dateRange), // No franchiseId = all franchises
  //       this.analyticsService.getApplicationAnalytics(dateRange), // No franchiseId = all franchises
  //       this.analyticsService.getCompanyAnalytics(dateRange), // No franchiseId = all franchises
  //       this.analyticsService.getUserAnalytics(dateRange), // No franchiseId = all franchises
  //       this.dashboardService.getAdminOverview(), // Get franchise data
  //     ]);

  //     return {
  //       success: true,
  //       data: {
  //         totalJobs: jobAnalytics.totalJobs || 0,
  //         totalApplications: applicationAnalytics.totalApplications || 0,
  //         activeCompanies: companyAnalytics.activeCompanies || 0,
  //         activeUsers: userAnalytics.activeUsers || 0,
  //         totalFranchises: franchiseData.data?.totalFranchises || 0,
  //         activeFranchises: franchiseData.data?.activeFranchises || 0,
  //         inactiveFranchises: franchiseData.data?.inactiveFranchises || 0,
  //       },
  //     };
  //   } catch (error) {
  //     throw new HttpException(
  //       { message: error.message || 'Error fetching admin analytics overview' },
  //       HttpStatus.INTERNAL_SERVER_ERROR,
  //     );
  //   }
  // }

  // Admin Analytics Endpoints (aggregate across all franchises)
  @Public()
  @Get('analytics/overview')
  async getAdminAnalyticsOverview(@Query('dateRange') dateRange: number = 30) {
    try {
      const [
        jobAnalytics,
        applicationAnalytics,
        companyAnalytics,
        userAnalytics,
        franchiseData,
      ] = await Promise.all([
        this.analyticsService.getJobAnalytics(dateRange), // No franchiseId = all franchises
        this.analyticsService.getApplicationAnalytics(dateRange), // No franchiseId = all franchises
        this.analyticsService.getCompanyAnalytics(dateRange), // No franchiseId = all franchises
        this.analyticsService.getUserAnalytics(dateRange), // No franchiseId = all franchises
        this.dashboardService.getAdminOverview(), // Get franchise data
      ]);

      return {
        success: true,
        data: {
          totalJobs: jobAnalytics.totalJobs || 0,
          totalApplications: applicationAnalytics.totalApplications || 0,
          activeCompanies: companyAnalytics.activeCompanies || 0,
          activeUsers: userAnalytics.activeUsers || 0,
          totalFranchises: franchiseData.data?.totalFranchises || 0,
          activeFranchises: franchiseData.data?.activeFranchises || 0,
          inactiveFranchises: franchiseData.data?.inactiveFranchises || 0,
        },
      };
    } catch (error) {
      throw new HttpException(
        { message: error.message || 'Error fetching admin analytics overview' },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
  @Public()
  @Get('analytics/jobs')
  async getAdminJobAnalytics(@Query('dateRange') dateRange: number = 30) {
    try {
      const jobAnalytics =
        await this.analyticsService.getJobAnalytics(dateRange); // No franchiseId = all franchises
      return {
        success: true,
        data: jobAnalytics,
      };
    } catch (error) {
      throw new HttpException(
        { message: error.message || 'Error fetching admin job analytics' },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('analytics/applications')
  async getAdminApplicationAnalytics(
    @Query('dateRange') dateRange: number = 30,
  ) {
    try {
      // console.log(' Admin Application Analytics API Called:');
      // console.log('Date Range:', dateRange);
      // console.log('Scope: ALL FRANCHISES (Admin Level)');

      const applicationAnalytics =
        await this.analyticsService.getApplicationAnalytics(dateRange); // No franchiseId = all franchises

      // console.log(' Admin Application Analytics Result:', {
      //   totalApplications: applicationAnalytics.totalApplications,
      //   monthlyApplicationsCount:
      //     applicationAnalytics.monthlyApplications?.length || 0,
      // });
      return {
        success: true,
        data: applicationAnalytics,
      };
    } catch (error) {
      // console.error('❌ Admin Application Analytics Error:', error);
      throw new HttpException(
        {
          message:
            error.message || 'Error fetching admin application analytics',
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('analytics/companies')
  async getAdminCompanyAnalytics(@Query('dateRange') dateRange: number = 30) {
    try {
      const companyAnalytics =
        await this.analyticsService.getCompanyAnalytics(dateRange); // No franchiseId = all franchises
      return {
        success: true,
        data: companyAnalytics,
      };
    } catch (error) {
      throw new HttpException(
        { message: error.message || 'Error fetching admin company analytics' },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('analytics/users')
  async getAdminUserAnalytics(@Query('dateRange') dateRange: number = 30) {
    try {
      const userAnalytics =
        await this.analyticsService.getUserAnalytics(dateRange); // No franchiseId = all franchises
      return {
        success: true,
        data: userAnalytics,
      };
    } catch (error) {
      throw new HttpException(
        { message: error.message || 'Error fetching admin user analytics' },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('analytics/franchises')
  async getAdminFranchiseAnalytics() {
    try {
      const franchiseData = await this.dashboardService.getAdminOverview();
      return {
        success: true,
        data: franchiseData.data,
      };
    } catch (error) {
      throw new HttpException(
        {
          message: error.message || 'Error fetching admin franchise analytics',
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  // Auto-complete endpoints
  @Public()
  @Get('autocomplete/jobs')
  async getJobSuggestions(@Query('q') query: string) {
    if (!query || query.trim().length < 2) {
      return { suggestions: [] };
    }
    return await this.dashboardService.getJobSuggestions(query.trim());
  }

  @Public()
  @Get('autocomplete/companies')
  async getCompanySuggestions(@Query('q') query: string) {
    if (!query || query.trim().length < 2) {
      return { suggestions: [] };
    }
    return await this.dashboardService.getCompanySuggestions(query.trim());
  }

  @Public()
  @Get('autocomplete/search')
  async getSearchSuggestions(@Query('q') query: string) {
    if (!query || query.trim().length < 2) {
      return { suggestions: { jobs: [], companies: [] } };
    }
    return await this.dashboardService.getSearchSuggestions(query.trim());
  }

  //admin dashboard endpoints
}
