import {
  Controller,
  Get,
  Query,
  ParseIntPipe,
  Param,
  UseGuards,
  Post,
  Delete,
} from '@nestjs/common';
import { MobileOptionalSessionGuard } from '../common/mobile-optional-session.guard';
import { OptionalMobileUser } from '../common/optional-mobile-user.decorator';
import { UserEntity } from '../../modules/user/entities/user.entity';
import { ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { Public } from '../../modules/auth/public.decorator';
import { MobileDashboardService } from './mobile-dashboard.service';

@ApiTags('mobile_dashboard')
@Controller('mobile/dashboard')
export class MobileDashboardController {
  constructor(
    private readonly mobileDashboardService: MobileDashboardService,
  ) { }

  @Public()
  @Get()
  @ApiOperation({
    summary: 'Get aggregated mobile dashboard data after login',
  })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'city', required: false, type: String })
  @ApiQuery({ name: 'type', required: false, type: String })
  @ApiQuery({ name: 'industry', required: false, type: String })
  @ApiQuery({ name: 'education', required: false, type: String })
  async getDashboard(
    @Query('userId', ParseIntPipe) userId: number,
    @Query('limit') limit?: string,
    @Query('city') city?: string,
    @Query('type') type?: string,
    @Query('industry') industry?: string,
    @Query('education') education?: string,
  ) {
    return this.mobileDashboardService.getDashboard({
      userId,
      limit: this.toLimit(limit),
      city,
      type,
      industry,
      education,
    });
  }

  // ---------------------------------Search---------------------------------
  @Public()
  @Get('search')
  @ApiOperation({
    summary: 'Search jobs (mobile)',
  })
  @ApiQuery({ name: 'query', required: false, type: String })
  @ApiQuery({ name: 'location', required: false, type: String })
  @ApiQuery({ name: 'education', required: false, type: String })

  // job type filters
  @ApiQuery({ name: 'jobTypes', required: false, type: String })
  @ApiQuery({ name: 'jobTypeIds', required: false, type: String })

  // city filters
  @ApiQuery({ name: 'cities', required: false, type: String })
  @ApiQuery({ name: 'cityIds', required: false, type: String })

  // industry filters
  @ApiQuery({ name: 'industryIds', required: false, type: String })

  // education id filters
  @ApiQuery({ name: 'educationIds', required: false, type: String })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  async search(
    @Query('query') query?: string,
    @Query('location') location?: string,
    @Query('education') education?: string,
    @Query('jobTypes') jobTypes?: string,
    @Query('jobTypeIds') jobTypeIds?: string,
    @Query('cities') cities?: string,
    @Query('cityIds') cityIds?: string,
    @Query('industryIds') industryIds?: string,
    @Query('educationIds') educationIds?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.mobileDashboardService.searchDashboardJobsMobile({
      query: query ?? undefined,
      location: location ?? undefined,
      education: education ?? undefined,
      jobTypes: jobTypes ?? undefined,
      jobTypeIds: jobTypeIds ?? undefined,
      cities: cities ?? undefined,
      cityIds: cityIds ?? undefined,
      industryIds: industryIds ?? undefined,
      educationIds: educationIds ?? undefined,
      page: this.toPage(page),
      limit: this.toLimit(limit),
    });
  }

  // ---------------------------------Filter Jobs---------------------------------
  @Public()
  @Get('jobs/filter')
  @ApiOperation({
    summary: 'Filter jobs (mobile dashboard)',
  })
  // job types
  @ApiQuery({ name: 'jobTypes', required: false, type: String })
  @ApiQuery({ name: 'jobTypeIds', required: false, type: String })
  // cities
  @ApiQuery({ name: 'cities', required: false, type: String })
  @ApiQuery({ name: 'cityIds', required: false, type: String })
  // industries
  @ApiQuery({ name: 'industryIds', required: false, type: String })
  // education
  @ApiQuery({ name: 'educationIds', required: false, type: String })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  async filterJobs(
    @Query('jobTypes') jobTypes?: string,
    @Query('jobTypeIds') jobTypeIds?: string,
    @Query('cities') cities?: string,
    @Query('cityIds') cityIds?: string,
    @Query('industryIds') industryIds?: string,
    @Query('educationIds') educationIds?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.mobileDashboardService.filterDashboardJobsMobile({
      jobTypes: jobTypes ?? undefined,
      jobTypeIds: jobTypeIds ?? undefined,
      cities: cities ?? undefined,
      cityIds: cityIds ?? undefined,
      industryIds: industryIds ?? undefined,
      educationIds: educationIds ?? undefined,
      page: this.toPage(page),
      limit: this.toLimit(limit),
    });
  }

  // ---------------------------------Filter Metadata---------------------------------
  @Public()
  @Get('filter/job-types')
  @ApiOperation({ summary: 'Get job types for mobile filter UI' })
  async getJobTypesForFilter() {
    return this.mobileDashboardService.getMobileJobTypesForFilter();
  }

  @Public()
  @Get('filter/cities')
  @ApiOperation({ summary: 'Search cities for mobile filter UI' })
  @ApiQuery({ name: 'query', required: false, type: String })
  async getCitiesForFilter(@Query('query') query?: string) {
    return this.mobileDashboardService.getMobileCitiesForFilter({ query });
  }

  @Public()
  @Get('filter/industries')
  @ApiOperation({ summary: 'Get industries for mobile filter UI' })
  async getIndustriesForFilter() {
    return this.mobileDashboardService.getMobileIndustriesForFilter();
  }

  @Public()
  @Get('filter/education-levels')
  @ApiOperation({ summary: 'Get education levels for mobile filter UI' })
  async getEducationLevelsForFilter() {
    return this.mobileDashboardService.getMobileEducationLevelsForFilter();
  }

  // ---------------------------------Profile Jobs---------------------------------
  @Public()
  @Get('jobs')
  @ApiOperation({
    summary: 'Get jobs based on seeker profile and location',
  })
  @ApiQuery({ name: 'userId', required: false, type: Number })
  @ApiQuery({ name: 'cityId', required: false, type: Number })
  @ApiQuery({ name: 'areaId', required: false, type: Number })
  @ApiQuery({ name: 'roleId', required: false, type: Number })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  async getJobsForProfile(
    @Query('userId') userId?: string,
    @Query('cityId') cityId?: string,
    @Query('areaId') areaId?: string,
    @Query('roleId') roleId?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    return this.mobileDashboardService.getJobsForProfile({
      userId: this.toOptionalNumber(userId),
      cityId: this.toOptionalNumber(cityId),
      areaId: this.toOptionalNumber(areaId),
      roleId: this.toOptionalNumber(roleId),
      page: this.toPage(page),
      limit: this.toLimit(limit),
    });
  }

  @Public()
  @UseGuards(MobileOptionalSessionGuard)
  @Get('jobs/:id')
  @ApiOperation({
    summary: 'Get full job details for mobile app',
  })
  async getJobDetails(
    @Param('id', ParseIntPipe) jobId: number,
    @Query('userId') userId?: string,
  ) {
    const resolvedUserId = this.toOptionalNumber(userId);
    return this.mobileDashboardService.getJobDetails(jobId, resolvedUserId);
  }

  @Public()
  @Get('recommended-jobs')
  @ApiOperation({
    summary: 'Get recommended jobs for seeker mobile dashboard',
  })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({ name: 'city', required: false, type: String })
  @ApiQuery({ name: 'type', required: false, type: String })
  @ApiQuery({ name: 'industry', required: false, type: String })
  @ApiQuery({ name: 'education', required: false, type: String })
  async getRecommendedJobs(
    @Query('userId', ParseIntPipe) userId: number,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('city') city?: string,
    @Query('type') type?: string,
    @Query('industry') industry?: string,
    @Query('education') education?: string,
  ) {
    return this.mobileDashboardService.getRecommendedJobs({
      userId,
      page: this.toPage(page),
      limit: this.toLimit(limit),
      city,
      type,
      industry,
      education,
    });
  }

  @Public()
  @Get('top-companies')
  @ApiOperation({ summary: 'Get top companies with open positions' })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  async getTopCompanies(@Query('limit') limit?: string) {
    return this.mobileDashboardService.getTopCompanies(this.toLimit(limit));
  }

  // ---------------------------------Company Jobs---------------------------------
  // ---------------------------------Jobs Saved/Unsaved---------------------------------
  @Public()
  @Post('jobs/:jobPostId/save')
  @ApiOperation({ summary: 'Save/bookmark a job from mobile dashboard' })
  async saveJobFromDashboard(
    @Param('jobPostId') jobPostId: string,
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileDashboardService.saveJobFromDashboard(userId, jobPostId);
  }

  @Public()
  @Delete('jobs/:jobPostId/unsave')
  @ApiOperation({ summary: 'Unsave/remove bookmark a job from mobile dashboard' })
  async unsaveJobFromDashboard(
    @Param('jobPostId') jobPostId: string,
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileDashboardService.unsaveJobFromDashboard(userId, jobPostId);
  }

  @Public()
  @Get('jobs/:jobPostId/is_saved')
  @ApiOperation({ summary: 'Check whether a job is saved from mobile dashboard' })
  async isJobSavedFromDashboard(
    @Param('jobPostId') jobPostId: string,
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileDashboardService.isJobSavedFromDashboard(userId, jobPostId);
  }

  // ---------------------------------Company Jobs---------------------------------
  @Public()
  @Get('company/:companyId/jobs')
  @ApiOperation({
    summary: 'Get jobs posted by a specific company (mobile dashboard)',
  })
  @ApiQuery({ name: 'page', required: false, type: Number })
  @ApiQuery({ name: 'limit', required: false, type: Number })
  @ApiQuery({
    name: 'status',
    required: false,
    type: String,
    description: 'open|closed|paused|all',
  })
  async getCompanyJobs(
    @Param('companyId') companyId: number,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
    @Query('status') status?: string,
  ) {
    return this.mobileDashboardService.getCompanyJobs({
      companyId,
      page: this.toPage(page),
      limit: this.toLimit(limit),
      status: status || 'open',
    });
  }

  private toOptionalNumber(value?: string) {
    const numberValue = Number(value);
    return Number.isFinite(numberValue) && numberValue > 0
      ? numberValue
      : undefined;
  }

  private toPage(value?: string) {
    const page = Number(value);
    return Number.isFinite(page) && page > 0 ? page : 1;
  }

  private toLimit(value?: string) {
    const limit = Number(value);
    if (!Number.isFinite(limit) || limit <= 0) {
      return 10;
    }

    return Math.min(limit, 50);
  }
}
