import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Post,
  Put,
  Query,
  Res,
  UploadedFile,
  UseInterceptors,
  BadRequestException,
} from '@nestjs/common';
import { Response } from 'express';
import {
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiQuery,
  ApiTags,
} from '@nestjs/swagger';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';

import { Public } from '../../../modules/auth/public.decorator';
import { MobileSeekerProfileSettingsService } from './mobile-seeker-profile-settings.service';

@ApiTags('mobile_seeker_profile_settings')
@Controller('mobile/seeker')
export class MobileSeekerProfileSettingsController {
  constructor(
    private readonly mobileSeekerProfileSettingsService: MobileSeekerProfileSettingsService,
  ) { }

  @Public()
  @Get('profile_settings')
  @ApiOperation({
    summary: 'Get aggregated seeker profile data for mobile app',
  })
  @ApiQuery({
    name: 'userId',
    required: true,
    type: Number,
    description: 'User ID',
  })
  async getMobileSeekerProfile(@Query('userId', ParseIntPipe) userId: number) {
    return this.mobileSeekerProfileSettingsService.getProfileSettings(userId);
  }

  @Public()
  @Get('profile_editable')
  @ApiOperation({
    summary: 'Get mobile editable seeker profile screen data',
  })
  @ApiQuery({
    name: 'userId',
    required: true,
    type: Number,
    description: 'User ID',
  })
  async getMobileEditableProfile(
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.getEditableProfile(userId);
  }

  @Public()
  @Get('profile_editable/basic')
  @ApiOperation({
    summary: 'Get basic details edit form prefill for mobile app',
  })
  @ApiQuery({
    name: 'userId',
    required: true,
    type: Number,
    description: 'User ID',
  })
  async getMobileBasicDetailsEditForm(
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.getBasicDetailsEditForm(
      userId,
    );
  }

  @Public()
  @Put('profile_editable/basic')
  @ApiOperation({ summary: 'Update mobile seeker profile basic details' })
  @ApiBody({
    schema: {
      type: 'object',
      description:
        'camelCase fields — GET and PUT use the same names. White collar includes email and full address; blue collar has no email and uses preferredWorkCityId (state derived from city on GET).',
      properties: {
        userId: { type: 'number' },
        fullName: { type: 'string' },
        profilePicture: { type: 'string', description: 'Path/URL of profile picture' },
        professionalTitle: { type: 'string' },
        phone: { type: 'string' },
        email: {
          type: 'string',
          description: 'White collar only — not used for blue_collar',
        },
        dateOfBirth: { type: 'string', format: 'date' },
        gender: { type: 'string' },
        educationId: { type: 'number' },
        experiencesId: { type: 'number' },
        selectedRoleCategory: {
          type: 'string',
          enum: ['white_collar', 'blue_collar'],
        },
        currentAddress: {
          type: 'string',
          description: 'White collar: street address',
        },
        pincode: { type: 'string', description: 'White collar: pincode' },
        areaId: {
          type: 'number',
          description: 'White collar only: area ID from pincode',
        },
        cityId: {
          type: 'number',
          description: 'White collar: communication city ID',
        },
        preferredWorkCityId: {
          type: 'number',
          description:
            'Blue collar: preferred work city ID (PUT; also accepts cityId for backward compatibility)',
        },
      },
      required: ['userId'],
    },
  })
  async updateMobileProfileBasic(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.updateBasicDetails(body);
  }

  @Public()
  @Put('profile_editable/skills')
  @ApiOperation({ summary: 'Update mobile seeker profile skills' })
  async updateMobileProfileSkills(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.updateSkills(body);
  }

  @Public()
  @Put('profile_editable/languages')
  @ApiOperation({ summary: 'Update mobile seeker profile languages' })
  async updateMobileProfileLanguages(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.updateLanguages(body);
  }

  @Public()
  @Post('profile_editable/resume')
  @ApiOperation({ summary: 'Upload mobile seeker resume' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        name: { type: 'string' },
        resume: { type: 'string', format: 'binary' },
      },
      required: ['userId', 'resume'],
    },
  })
  @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 },
      fileFilter: (req, file, cb) => {
        if (!file.originalname.match(/\.(pdf|doc|docx)$/i)) {
          return cb(new BadRequestException('Only document files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadMobileProfileResume(
    @UploadedFile() file: Express.Multer.File,
    @Body() body: any,
    @Body('name') name?: string,
  ) {
    return this.mobileSeekerProfileSettingsService.uploadResume(
      body?.userId ?? body?.user_id,
      file,
      name,
    );
  }

  @Public()
  @Delete('profile_editable/resume/:resumeId')
  @ApiOperation({ summary: 'Delete mobile seeker resume' })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  async deleteMobileProfileResume(
    @Param('resumeId', ParseIntPipe) resumeId: number,
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.deleteResume(
      userId,
      resumeId,
    );
  }

  @Public()
  @Get('profile_editable/resume')
  @ApiOperation({ summary: 'Get mobile seeker resumes' })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  async getMobileProfileResumes(@Query('userId', ParseIntPipe) userId: number) {
    return this.mobileSeekerProfileSettingsService.getResumes(userId);
  }

  @Public()
  @Put('profile_editable/resume/:resumeId')
  @ApiOperation({ summary: 'Update mobile seeker resume' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        name: { type: 'string' },
        resume: { type: 'string', format: 'binary' },
      },
      required: ['userId'],
    },
  })
  @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 },
      fileFilter: (req, file, cb) => {
        if (!file.originalname.match(/\.(pdf|doc|docx)$/i)) {
          return cb(new BadRequestException('Only document files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async updateMobileProfileResume(
    @Param('resumeId', ParseIntPipe) resumeId: number,
    @UploadedFile() file: Express.Multer.File,
    @Body() body: any,
    @Body('name') name?: string,
  ) {
    return this.mobileSeekerProfileSettingsService.updateResume(
      body?.userId ?? body?.user_id,
      resumeId,
      file,
      name,
    );
  }

  @Public()
  @Post('profile_editable/work_experience')
  @ApiOperation({ summary: 'Add mobile seeker work experience' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number', description: 'User ID of the seeker' },
        company: { type: 'string' },
        department: { type: 'string' },
        designation: { type: 'string' },
        start_date: {
          type: 'string',
          format: 'date',
          description: 'YYYY-MM-DD',
        },
        end_date: {
          type: 'string',
          format: 'date',
          description: 'YYYY-MM-DD (Optional if current is true)',
        },
        current: {
          type: 'boolean',
          description: 'Set to true if currently working here',
        },
        responsibilities: { type: 'string' },
      },
      required: ['userId', 'company', 'designation', 'start_date'],
    },
  })
  async addMobileWorkExperience(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.addWorkExperience(body);
  }

  @Public()
  @Put('profile_editable/work_experience/:id')
  @ApiOperation({ summary: 'Update mobile seeker work experience' })
  async updateMobileWorkExperience(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: any,
  ) {
    return this.mobileSeekerProfileSettingsService.updateWorkExperience(
      id,
      body,
    );
  }

  @Public()
  @Delete('profile_editable/work_experience/:id')
  @ApiOperation({ summary: 'Delete mobile seeker work experience' })
  async deleteMobileWorkExperience(@Param('id', ParseIntPipe) id: number) {
    return this.mobileSeekerProfileSettingsService.deleteWorkExperience(id);
  }

  @Public()
  @Get('profile_editable/roles_data')
  @ApiOperation({ summary: 'Get available roles and experiences for blue collar seekers' })
  @ApiQuery({ name: 'userId', required: false, type: Number })
  async getRolesData(@Query('userId') userId?: number) {
    return this.mobileSeekerProfileSettingsService.getRolesData(userId);
  }

  @Public()
  @Put('profile_editable/roles_data')
  @ApiOperation({ summary: 'Bulk update mobile blue collar seeker role experiences via roles_data route' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        roleExperiences: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              roleId: { type: 'number' },
              experienceId: { type: 'number' }
            }
          }
        }
      },
      required: ['userId', 'roleExperiences']
    }
  })
  async bulkUpdateMobileRolesData(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.bulkUpdateRoleExperiences(body);
  }

  @Public()
  @Put('profile_editable/role_experiences')
  @ApiOperation({ summary: 'Bulk update mobile blue collar seeker role experiences' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        roleExperiences: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              roleId: { type: 'number' },
              experienceId: { type: 'number' }
            }
          }
        }
      },
      required: ['userId', 'roleExperiences']
    }
  })
  async bulkUpdateMobileRoleExperiences(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.bulkUpdateRoleExperiences(body);
  }

  @Public()
  @Post('profile_editable/education')
  @ApiOperation({ summary: 'Add mobile seeker education' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        educationLevelId: { type: 'number' },
        institute_name: { type: 'string' },
        degree: { type: 'string' },
        degree_id: { type: 'number' },
        specialization: { type: 'string' },
        specialization_id: { type: 'number' },
        month: { type: 'string' },
        year: { type: 'number' },
      },
      required: ['userId', 'institute_name'],
    },
  })
  async addMobileEducation(@Body() body: any) {
    return this.mobileSeekerProfileSettingsService.addEducation(body);
  }

  @Public()
  @Put('profile_editable/education/:id')
  @ApiOperation({ summary: 'Update mobile seeker education' })
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        educationLevelId: { type: 'number' },
        institute_name: { type: 'string' },
        degree: { type: 'string' },
        degree_id: { type: 'number' },
        specialization: { type: 'string' },
        specialization_id: { type: 'number' },
        month: { type: 'string' },
        year: { type: 'number' },
      },
    },
  })
  async updateMobileEducation(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: any,
  ) {
    return this.mobileSeekerProfileSettingsService.updateEducation(id, body);
  }

  @Public()
  @Delete('profile_editable/education/:id')
  @ApiOperation({ summary: 'Delete mobile seeker education' })
  async deleteMobileEducation(@Param('id', ParseIntPipe) id: number) {
    return this.mobileSeekerProfileSettingsService.deleteEducation(id);
  }

  @Public()
  @Get('profile/:id')
  @ApiOperation({
    summary: 'Get public seeker profile view for mobile app',
  })
  async getPublicMobileSeekerProfile(
    @Param('id', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.getPublicProfile(userId);
  }

  @Public()
  @Put('profile_editable/profile_picture')
  @ApiOperation({ summary: 'Upload/Update mobile seeker profile picture' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        userId: { type: 'number' },
        profilePicture: { type: 'string', format: 'binary' },
      },
      required: ['userId', 'profilePicture'],
    },
  })
  @UseInterceptors(
    FileInterceptor('profilePicture', {
      storage: diskStorage({
        destination: './uploads/profile-pictures',
        filename: (req, file, cb) => {
          const uniqueSuffix =
            Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, uniqueSuffix + extname(file.originalname));
        },
      }),
      limits: { fileSize: 5 * 1024 * 1024 }, // 5MB limit
      fileFilter: (req, file, cb) => {
        if (!file.mimetype.match(/^image/)) {
          return cb(new Error('Only image files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadMobileProfilePicture(
    @UploadedFile() file: Express.Multer.File,
    @Body('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.uploadProfilePicture(
      userId,
      file,
    );
  }

  @Public()
  @Delete('profile_editable/profile_picture')
  @ApiOperation({ summary: 'Delete mobile seeker profile picture' })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  async deleteMobileProfilePicture(
    @Query('userId', ParseIntPipe) userId: number,
  ) {
    return this.mobileSeekerProfileSettingsService.deleteProfilePicture(userId);
  }

  @Public()
  @Get('profile_editable/profile_picture')
  @ApiOperation({ summary: 'Get/See mobile seeker profile picture' })
  @ApiQuery({ name: 'userId', required: true, type: Number })
  async getMobileProfilePicture(
    @Query('userId', ParseIntPipe) userId: number,
    @Res() res: Response,
  ) {
    return this.mobileSeekerProfileSettingsService.getProfilePicture(userId, res);
  }
}
