import {
  Controller,
  Get,
  HttpCode,
  HttpStatus,
  Inject,
  NotFoundException,
  Optional,
  Param,
  Post,
  Query,
  UseGuards,
} from '@nestjs/common';
import { AdminGuard } from './admin.guard.js';
import { QueueService } from '../queue/queue.service.js';
import type { JobDto, JobListDto, JobStatus, QueueListDto } from '../queue/queue-admin.dto.js';

@Controller('api/admin/jobs')
@UseGuards(AdminGuard)
export class AdminJobsController {
  constructor(
    @Optional()
    @Inject(QueueService)
    private readonly queueService: QueueService | null,
  ) {}

  /**
   * GET /api/admin/jobs
   * List jobs across all queues. Optional ?status=active|completed|failed|waiting|delayed
   */
  @Get()
  async listJobs(@Query('status') status?: string): Promise<JobListDto> {
    if (!this.queueService) {
      return { jobs: [], total: 0 };
    }

    const validStatuses: JobStatus[] = ['active', 'completed', 'failed', 'waiting', 'delayed'];
    const normalised = status as JobStatus | undefined;

    if (normalised && !validStatuses.includes(normalised)) {
      return { jobs: [], total: 0 };
    }

    const jobs: JobDto[] = await this.queueService.listJobs(normalised);
    return { jobs, total: jobs.length };
  }

  /**
   * POST /api/admin/jobs/:id/retry
   * Retry a specific failed job.  The id is "<queue>__<bullmq-job-id>".
   */
  @Post(':id/retry')
  @HttpCode(HttpStatus.OK)
  async retryJob(@Param('id') id: string): Promise<{ ok: boolean; message: string }> {
    if (!this.queueService) {
      throw new NotFoundException('Queue service is not available');
    }

    const result = await this.queueService.retryJob(id);
    if (!result.ok) {
      throw new NotFoundException(result.message);
    }

    return result;
  }

  /**
   * GET /api/admin/jobs/queues
   * Return status for all managed queues.
   */
  @Get('queues')
  async listQueues(): Promise<QueueListDto> {
    if (!this.queueService) {
      return { queues: [] };
    }

    const health = await this.queueService.getHealthStatus();
    const queues = Object.entries(health.queues).map(([name, stats]) => ({
      name,
      waiting: stats.waiting,
      active: stats.active,
      completed: stats.completed,
      failed: stats.failed,
      delayed: 0,
      paused: stats.paused,
    }));

    return { queues };
  }

  /**
   * POST /api/admin/jobs/queues/:name/pause
   * Pause the named queue.
   */
  @Post('queues/:name/pause')
  @HttpCode(HttpStatus.OK)
  async pauseQueue(@Param('name') name: string): Promise<{ ok: boolean; message: string }> {
    if (!this.queueService) {
      throw new NotFoundException('Queue service is not available');
    }

    const result = await this.queueService.pauseQueue(name);
    if (!result.ok) {
      throw new NotFoundException(result.message);
    }

    return result;
  }

  /**
   * POST /api/admin/jobs/queues/:name/resume
   * Resume the named queue.
   */
  @Post('queues/:name/resume')
  @HttpCode(HttpStatus.OK)
  async resumeQueue(@Param('name') name: string): Promise<{ ok: boolean; message: string }> {
    if (!this.queueService) {
      throw new NotFoundException('Queue service is not available');
    }

    const result = await this.queueService.resumeQueue(name);
    if (!result.ok) {
      throw new NotFoundException(result.message);
    }

    return result;
  }
}
