import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TaskSchedulerService } from '../scheduler/task-scheduler.service';
import { CreateTaskDto, UpdateTaskDto } from './tasks.dto';
import { InspectionTaskEntity } from './inspection-task.entity';

@Injectable()
export class TasksService {
  constructor(
    @InjectRepository(InspectionTaskEntity)
    private readonly taskRepository: Repository<InspectionTaskEntity>,
    private readonly taskSchedulerService: TaskSchedulerService,
  ) {}

  async getTasks(filters: {
    keyword?: string;
    status?: 'enabled' | 'disabled';
    preferredExecutor?: 'browser' | 'agent-s';
  }) {
    const query = this.taskRepository.createQueryBuilder('task');

    if (filters.keyword) {
      query.andWhere(
        '(task.name LIKE :keyword OR task.siteUrl LIKE :keyword OR task.serviceKey LIKE :keyword)',
        { keyword: `%${filters.keyword}%` },
      );
    }
    if (filters.status) {
      query.andWhere('task.status = :status', { status: filters.status });
    }
    if (filters.preferredExecutor) {
      query.andWhere('task.preferredExecutor = :preferredExecutor', {
        preferredExecutor: filters.preferredExecutor,
      });
    }

    const [list, total] = await query
      .orderBy('task.createdAt', 'DESC')
      .getManyAndCount();
    return { list, total };
  }

  async createTask(dto: CreateTaskDto) {
    this.taskSchedulerService.validateCron(dto.cronExpr);
    const task = this.taskRepository.create({
      ...dto,
      status: 'enabled',
      lastRunAt: null,
    });

    await this.taskRepository.save(task);
    await this.taskSchedulerService.syncTask(task.id);
    return { taskId: task.id, status: task.status };
  }

  async updateTask(id: string, dto: UpdateTaskDto) {
    this.taskSchedulerService.validateCron(dto.cronExpr);
    const task = await this.taskRepository.findOneBy({ id });
    if (!task) {
      throw new NotFoundException('巡检任务不存在');
    }

    task.name = dto.name;
    task.siteUrl = dto.siteUrl;
    task.cronExpr = dto.cronExpr;
    task.serviceKey = dto.serviceKey;
    task.preferredExecutor = dto.preferredExecutor;
    task.allowAgentFallback = dto.allowAgentFallback;
    task.stepsJson = dto.stepsJson;

    await this.taskRepository.save(task);
    await this.taskSchedulerService.syncTask(task.id);
    return { taskId: task.id, status: task.status };
  }

  async updateStatus(id: string, status: 'enabled' | 'disabled') {
    const task = await this.taskRepository.findOneBy({ id });
    if (!task) {
      throw new NotFoundException('巡检任务不存在');
    }
    task.status = status;
    await this.taskRepository.save(task);
    await this.taskSchedulerService.syncTask(task.id);
    return this.taskRepository.findOneByOrFail({ id });
  }

  async deleteTask(id: string) {
    const task = await this.taskRepository.findOneBy({ id });
    if (!task) {
      throw new NotFoundException('巡检任务不存在');
    }
    await this.taskSchedulerService.removeTask(id);
    await this.taskRepository.delete({ id });
    return { deleted: true, taskId: id };
  }

  async deleteTasks(input: {
    taskIds?: string[];
    filters?: {
      keyword?: string;
      status?: 'enabled' | 'disabled';
      preferredExecutor?: 'browser' | 'agent-s';
    };
  }) {
    let idsToDelete = (input.taskIds ?? []).filter(Boolean);
    if (!idsToDelete.length && input.filters) {
      const result = await this.getTasks(input.filters);
      idsToDelete = result.list.map((item) => item.id);
    }
    if (!idsToDelete.length) {
      return { deleted: 0, taskIds: [] as string[] };
    }

    for (const taskId of idsToDelete) {
      await this.taskSchedulerService.removeTask(taskId);
    }
    await this.taskRepository
      .createQueryBuilder()
      .delete()
      .from(InspectionTaskEntity)
      .where('id IN (:...ids)', { ids: idsToDelete })
      .execute();
    return { deleted: idsToDelete.length, taskIds: idsToDelete };
  }
}
