import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
  Req,
  Res,
  UseGuards,
  UsePipes,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { getPermissionContext } from '../../common/access-control/permission-request.util';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { ZodValidationPipe } from '../../common/pipes/zod-validation.pipe';
import { JwtAuthGuard } from '../owner/guards/jwt.guard';
import {
  bulkUpdateApplicationStatusDto,
  bulkUpdateApplicationStatusSchema,
  createJobApplicationDto,
  createJobApplicationSchema,
  createJobPostingDto,
  createJobPostingSchema,
  createRecruitmentTaskDto,
  createRecruitmentTaskSchema,
  updateRecruitmentTaskDto,
  updateRecruitmentTaskSchema,
  assignRecruitmentTasksDto,
  assignRecruitmentTasksSchema,
  createTenantApiKeyDto,
  createTenantApiKeySchema,
  jobApplicationFilterDto,
  jobApplicationFilterSchema,
  jobPostingFilterDto,
  jobPostingFilterSchema,
  recruitmentTaskFilterDto,
  recruitmentTaskFilterSchema,
  updateApplicationStatusDto,
  updateApplicationStatusSchema,
  updateJobApplicationDto,
  updateJobApplicationSchema,
  updateJobPostingDto,
  updateJobPostingSchema,
  scheduleInterviewDto,
  scheduleInterviewSchema,
  cancelInterviewDto,
  cancelInterviewSchema,
} from './recruitment.dto';
import { RecruitmentService } from './recruitment.service';

@Controller()
export class RecruitmentController {
  constructor(private readonly service: RecruitmentService) {}

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createJobPostingSchema))
  @Post('job-postings/create')
  async createJobPosting(
    @Body() data: createJobPostingDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.createJobPosting(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(jobPostingFilterSchema))
  @Get('job-postings/filter')
  async getJobPostings(
    @Query() query: jobPostingFilterDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getJobPostings(
      query,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get('job-postings/find/:id')
  async getJobPostingById(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getJobPostingById(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateJobPostingSchema))
  @Patch('job-postings/update/:id')
  async updateJobPosting(
    @Param('id') id: string,
    @Body() data: updateJobPostingDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.updateJobPosting(
      id,
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete('job-postings/delete/:id')
  async deleteJobPosting(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.deleteJobPosting(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createJobApplicationSchema))
  @Post('job-applications/create')
  async createApplication(
    @Body() data: createJobApplicationDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    console.log(data);
    const result = await this.service.createApplication(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(jobApplicationFilterSchema))
  @Get('job-applications/filter')
  async getApplications(
    @Query() query: jobApplicationFilterDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getApplications(
      query,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get('job-applications/find/:id')
  async getApplicationById(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getApplicationById(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateJobApplicationSchema))
  @Patch('job-applications/update/:id')
  async updateApplication(
    @Param('id') id: string,
    @Body() data: updateJobApplicationDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.updateApplication(
      id,
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateApplicationStatusSchema))
  @Patch('job-applications/update-status/:id')
  async updateApplicationStatus(
    @Param('id') id: string,
    @Body() data: updateApplicationStatusDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.updateApplicationStatus(
      id,
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(bulkUpdateApplicationStatusSchema))
  @Patch('job-applications/bulk-update-status')
  async bulkUpdateApplicationStatus(
    @Body() data: bulkUpdateApplicationStatusDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.bulkUpdateApplicationStatus(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete('job-applications/:id')
  async deleteApplication(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.deleteApplication(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createRecruitmentTaskSchema))
  @Post('recruitment-tasks/create')
  async createTask(
    @Body() data: createRecruitmentTaskDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.createTask(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(updateRecruitmentTaskSchema))
  @Patch('recruitment-tasks/:id')
  async updateTask(
    @Param('id') id: string,
    @Body() data: updateRecruitmentTaskDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.updateTask(
      id,
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete('recruitment-tasks/:id')
  async deleteTask(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.deleteTask(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(assignRecruitmentTasksSchema))
  @Post('recruitment-tasks/assign-bulk')
  async assignBulkTasks(
    @Body() data: assignRecruitmentTasksDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.assignBulkTasks(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(recruitmentTaskFilterSchema))
  @Get('recruitment-tasks/filter')
  async getTasks(
    @Query() query: recruitmentTaskFilterDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getTasks(
      query,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Post('recruitment-tasks/send-email/:id')
  async sendTaskEmail(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.sendTaskEmail(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get('recruitment/stats')
  async getStats(
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.getStats(
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(createTenantApiKeySchema))
  @Post('tenant-api-keys/create')
  async createApiKey(
    @Body() data: createTenantApiKeyDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.createApiKey(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Get('tenant-api-keys/all')
  async listApiKeys(
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.listApiKeys(
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @Delete('tenant-api-keys/revoke/:id')
  async revokeApiKey(
    @Param('id') id: string,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.revokeApiKey(
      id,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(scheduleInterviewSchema))
  @Post('job-applications/schedule-interview')
  async scheduleInterview(
    @Body() data: scheduleInterviewDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.scheduleInterview(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }

  @UseGuards(JwtAuthGuard)
  @UsePipes(new ZodValidationPipe(cancelInterviewSchema))
  @Post('job-applications/cancel-interview')
  async cancelInterview(
    @Body() data: cancelInterviewDto,
    @CurrentUser() owner_id: string,
    @Req() req: Request,
    @Res() res: Response,
  ) {
    const result = await this.service.cancelInterview(
      data,
      owner_id,
      getPermissionContext(req.user as any),
    );
    return res.status(result.status).json(result);
  }
}
