import { Inject, Provide } from '@midwayjs/core';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { In, Repository } from 'typeorm';
import { ProjectPhaseEntity } from '../entity/phase';
import { ProjectTaskEntity } from '../entity/task';
import { ProjectInfoService } from './info';

/**
 * 项目阶段服务
 */
@Provide()
export class ProjectPhaseService extends BaseService {
  @InjectEntityModel(ProjectPhaseEntity)
  projectPhaseEntity: Repository<ProjectPhaseEntity>;

  @InjectEntityModel(ProjectTaskEntity)
  projectTaskEntity: Repository<ProjectTaskEntity>;

  @Inject()
  projectInfoService: ProjectInfoService;

  private affectedProjectIds = new Set<number>();

  private normalizeIds(ids: any): number[] {
    if (Array.isArray(ids)) {
      return ids.map(id => Number(id)).filter(Boolean);
    }
    if (typeof ids === 'string') {
      return ids
        .split(',')
        .map(id => Number(id))
        .filter(Boolean);
    }
    const id = Number(ids);
    return id ? [id] : [];
  }

  async modifyBefore(data: any, type: 'delete' | 'update' | 'add') {
    this.affectedProjectIds = new Set<number>();

    if (type === 'delete' || type === 'update') {
      const ids = type === 'delete' ? this.normalizeIds(data) : this.normalizeIds(data?.id);
      if (ids.length > 0) {
        const phases = await this.projectPhaseEntity.findBy({ id: In(ids) });
        for (const phase of phases) {
          this.affectedProjectIds.add(phase.projectId);
        }
      }
    }

    if (type !== 'delete' && data.projectId) {
      this.affectedProjectIds.add(Number(data.projectId));
    }
  }

  async modifyAfter(data: any, type: 'delete' | 'update' | 'add') {
    if (type === 'delete') {
      const ids = this.normalizeIds(data);
      if (ids.length > 0) {
        await this.projectTaskEntity.update({ phaseId: In(ids) }, { phaseId: null });
      }
    }

    if (type !== 'delete' && data.projectId) {
      this.affectedProjectIds.add(Number(data.projectId));
    }

    for (const projectId of this.affectedProjectIds) {
      await this.projectInfoService.recalcProgress(projectId);
    }
  }
}
