import {
  Controller,
  Get,
  Query,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiBearerAuth,
  ApiTags,
  ApiOperation,
  ApiResponse,
} from '@nestjs/swagger';
import { ReportsService } from './reports.service';
import { Public } from '../auth/public.decorator';

@Public()
@ApiTags('recruiter-reports')
@ApiBearerAuth('access-token')
@Controller('recruiter-reports')
export class ReportsController {
  constructor(private readonly reportsService: ReportsService) {}

  /**
   * Controller for Recruiter Reports Overview
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Overview Dashboard
   * Purpose: Provides global KPIs and a top companies summary based on applications and revenue.
   */
  @Get('overview')
  @ApiOperation({ summary: 'Get Overview Dashboard Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns KPIs and top companies table data',
  })
  async getOverview(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
    @Query('alertPage') alertPage?: string,
    @Query('alertLimit') alertLimit?: string,
  ) {
    try {
      return await this.reportsService.getOverview(
        from,
        to,
        company,
        alertPage ? parseInt(alertPage, 10) : undefined,
        alertLimit ? parseInt(alertLimit, 10) : undefined,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for CV Access Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> CV Access by Job Post
   * Purpose: Returns CV usage/downloads aggregated by company.
   */
  @Public()
  @Get('cv-access')
  @ApiOperation({ summary: 'Get CV Access Data' })
  @ApiResponse({ status: 200, description: 'Returns CV downloads per company' })
  async getCvAccess(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getCvAccess(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Jobs & Applications Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Jobs Applications
   * Purpose: Provides an aggregation of jobs posted and total applications received per company.
   */
  @Public()
  @Get('jobs-applications')
  @ApiOperation({ summary: 'Get Jobs and Applications Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns jobs and apps per company',
  })
  async getJobsApplications(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getJobsApplications(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Usage Limits Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Usage Limits
   * Purpose: Returns current CV usage against limits for active companies.
   */
  @Public()
  @Get('usage')
  @ApiOperation({ summary: 'Get Usage Limits Data' })
  @ApiResponse({ status: 200, description: 'Returns usage limits per company' })
  async getUsageLimits(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getUsageLimits(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Payments Plan Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Payments Plan
   * Purpose: Returns recent successful payments from companies to display in history.
   */
  @Public()
  @Get('payments')
  @ApiOperation({ summary: 'Get Payments History Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns recent successful payments',
  })
  async getPayments(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getPayments(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Top Jobs Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Top Jobs
   * Purpose: Returns the most applied-to active jobs with computed conversion rates.
   */
  @Public()
  @Get('top-jobs')
  @ApiOperation({ summary: 'Get Top Jobs Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns top performing jobs based on apps',
  })
  async getTopJobs(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getTopJobs(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Candidate Engagement Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Candidate Engagement
   * Purpose: Returns job engagement statistics (views, apply rates) and behavior details.
   */
  @Public()
  @Get('engagement')
  @ApiOperation({ summary: 'Get Candidate Engagement Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns engagement metrics per job',
  })
  async getEngagement(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getEngagement(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for Login & Session Activity Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> Login Session
   * Purpose: Returns login frequency and session details for recruiters.
   */
  @Public()
  @Get('sessions')
  @ApiOperation({ summary: 'Get Login Session Data' })
  @ApiResponse({
    status: 200,
    description: 'Returns login sessions per company',
  })
  async getSessions(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
  ) {
    try {
      return await this.reportsService.getSessions(from, to, company);
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * Controller for City-wise Analytics Report
   * Module: Recruiter Reports
   * Used in: Admin Dashboard -> Recruiter Reports -> City Analytics
   * Purpose: Provides city-wise job distribution, applications, and demand metrics.
   */
  @Public()
  @Get('city-analytics')
  @ApiOperation({ summary: 'Get Recruiter City-wise Analytics Report' })
  @ApiResponse({ status: 200, description: 'Returns city-wise metrics' })
  async getCityAnalytics(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('company') company?: string,
    @Query('state') state?: string,
    @Query('industry') industry?: string,
    @Query('distPage') distPage?: string,
    @Query('appsPage') appsPage?: string,
    @Query('demandPage') demandPage?: string,
    @Query('emptyPage') emptyPage?: string,
    @Query('distS') distS?: string,
    @Query('appsS') appsS?: string,
    @Query('demandS') demandS?: string,
    @Query('emptyS') emptyS?: string,
    @Query('page') page?: string,
    @Query('search') search?: string,
  ) {
    try {
      return await this.reportsService.getCityAnalytics(
        from,
        to,
        company,
        state,
        industry,
        distPage ? parseInt(distPage, 10) : 1,
        appsPage ? parseInt(appsPage, 10) : 1,
        demandPage ? parseInt(demandPage, 10) : 1,
        emptyPage ? parseInt(emptyPage, 10) : 1,
        distS,
        appsS,
        demandS,
        emptyS,
        page ? parseInt(page, 10) : 1,
        search,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Public()
  @Get('companies')
  @ApiOperation({ summary: 'Get List of Real Companies' })
  @ApiResponse({
    status: 200,
    description: 'Returns list of non-admin company names',
  })
  async getCompanies() {
    try {
      return await this.reportsService.getCompanies();
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}

@Public()
@ApiTags('associate-reports')
@ApiBearerAuth('access-token')
@Controller('associate-reports')
export class AssociateReportsController {
  constructor(private readonly reportsService: ReportsService) {}

  @Get('overview')
  @ApiOperation({ summary: 'Get Associate Overview Report' })
  async getAssociateOverview(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
  ) {
    try {
      return await this.reportsService.getAssociateOverview(
        from,
        to,
        associate,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('cv-access')
  @ApiOperation({ summary: 'Get Associate CV Access Report' })
  async getAssociateCvAccess(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
  ) {
    try {
      return await this.reportsService.getAssociateCvAccess(
        from,
        to,
        associate,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('jobs-applications')
  @ApiOperation({ summary: 'Get Associate Jobs & Applications Report' })
  async getAssociateJobsApplications(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
  ) {
    try {
      return await this.reportsService.getAssociateJobsApplications(
        from,
        to,
        associate,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('engagement')
  @ApiOperation({ summary: 'Get Associate Candidate Engagement Report' })
  async getAssociateEngagement(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
  ) {
    try {
      return await this.reportsService.getAssociateEngagement(
        from,
        to,
        associate,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('sessions')
  @ApiOperation({ summary: 'Get Associate Login Activity Report' })
  async getAssociateSessions(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
  ) {
    try {
      return await this.reportsService.getAssociateSessions(
        from,
        to,
        associate,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('city-job-posting')
  @ApiOperation({ summary: 'Get Associate City-wise Job Posting Report' })
  async getAssociateCityJobPosting(
    @Query('from') from?: string,
    @Query('to') to?: string,
    @Query('associate') associate?: string,
    @Query('state') state?: string,
    @Query('industry') industry?: string,
    @Query('page') page?: string,
    @Query('search') search?: string,
    @Query('distPage') distPage?: string,
    @Query('appsPage') appsPage?: string,
    @Query('demandPage') demandPage?: string,
    @Query('emptyPage') emptyPage?: string,
    @Query('distS') distS?: string,
    @Query('appsS') appsS?: string,
    @Query('demandS') demandS?: string,
    @Query('emptyS') emptyS?: string,
  ) {
    // Force compiler refresh for new signature
    try {
      return await this.reportsService.getAssociateCityJobPosting(
        from,
        to,
        associate,
        state,
        industry,
        page ? parseInt(page, 10) : 1,
        search,
        distPage ? parseInt(distPage, 10) : 1,
        appsPage ? parseInt(appsPage, 10) : 1,
        demandPage ? parseInt(demandPage, 10) : 1,
        emptyPage ? parseInt(emptyPage, 10) : 1,
        distS,
        appsS,
        demandS,
        emptyS,
      );
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Get('associates')
  @ApiOperation({ summary: 'Get Associate Names for Reports Filters' })
  async getAssociates() {
    try {
      return await this.reportsService.getAssociates();
    } catch (error: any) {
      throw new HttpException(
        { success: false, error: error.message },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
