import { ACGuard } from '@gadmin2n/nest-common';
import {
  Body,
  Controller,
  Get,
  NotFoundException,
  Param,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { AgendaService } from './agenda.service';

class JobIdsDto {
  jobIds: string[];
}

class JobsQueryDto {
  job?: string;
  state?: string;
  toggle?: string;
  module?: string;
  q?: string;
  skip?: number;
  limit?: number;
}

class JobLogsQueryDto {
  jobName: string;
  status?: string;
  before?: string;
  skip?: number;
  limit?: number;
}

@UseGuards(ACGuard)
@Controller('agenda')
@ApiTags('agenda')
export class AgendaController {
  constructor(private readonly agendaService: AgendaService) {}

  @Get('overview')
  @ApiOkResponse({ description: 'Get execution metrics overview (24h/total)' })
  async getOverview() {
    return this.agendaService.getMetricsOverview();
  }

  @Get('jobs')
  @ApiOkResponse({ description: 'List jobs with overview stats' })
  async getJobs(@Query() query: JobsQueryDto) {
    return this.agendaService.getJobs({
      job: query.job,
      state: query.state,
      toggle: query.toggle,
      module: query.module,
      q: query.q,
      skip: query.skip ? Number(query.skip) : 0,
      limit: query.limit ? Number(query.limit) : 20,
    });
  }

  @Post('requeue')
  @ApiOkResponse({ description: 'Requeue jobs by IDs' })
  async requeue(@Body() body: JobIdsDto) {
    return this.agendaService.requeueByIds(body.jobIds);
  }

  @Post('retry')
  @ApiOkResponse({ description: 'Retry failed jobs by IDs' })
  async retry(@Body() body: JobIdsDto) {
    return this.agendaService.retryByIds(body.jobIds);
  }

  @Post('delete')
  @ApiOkResponse({ description: 'Delete jobs by IDs' })
  async delete(@Body() body: JobIdsDto) {
    return this.agendaService.deleteByIds(body.jobIds);
  }

  @Post('disable')
  @ApiOkResponse({ description: 'Disable (pause) jobs by IDs' })
  async disable(@Body() body: JobIdsDto) {
    return this.agendaService.disableByIds(body.jobIds);
  }

  @Post('enable')
  @ApiOkResponse({ description: 'Enable (resume) jobs by IDs' })
  async enable(@Body() body: JobIdsDto) {
    return this.agendaService.enableByIds(body.jobIds);
  }

  @Get('job/:jobName')
  @ApiOkResponse({ description: 'Get single job detail with run statistics' })
  async getJobDetail(@Param('jobName') jobName: string) {
    const detail = await this.agendaService.getJobDetail(jobName);
    if (!detail) throw new NotFoundException(`Job "${jobName}" not found`);
    return detail;
  }

  @Get('logs')
  @ApiOkResponse({ description: 'Get execution history logs for a job' })
  async getLogs(@Query() query: JobLogsQueryDto) {
    return this.agendaService.getJobLogs({
      jobName: query.jobName,
      status: query.status,
      before: query.before,
      skip: query.skip ? Number(query.skip) : 0,
      limit: query.limit ? Number(query.limit) : 20,
    });
  }
}
