import { Injectable } from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { PERFORMANCE_ERROR_CODES } from '../constants/error-codes';
import { BusinessException } from '@common/exceptions/business.exception';

@Injectable()
export class StrategicObjectiveService {
  constructor(private readonly prisma: PrismaService) {}

  async findAll(query: { cycleId?: string; organizationId?: string }) {
    const where: any = { deletedAt: null };
    if (query.cycleId) where.cycleId = query.cycleId;
    if (query.organizationId) where.organizationId = query.organizationId;

    return this.prisma.strategicObjective.findMany({
      where,
      include: {
        assignments: {
          where: { deletedAt: null },
          include: { assignee: { select: { id: true, displayName: true, email: true } } },
        },
      },
      orderBy: { seq: 'asc' },
    });
  }

  async findById(id: string) {
    const objective = await this.prisma.strategicObjective.findFirst({
      where: { id, deletedAt: null },
      include: {
        assignments: {
          where: { deletedAt: null },
          include: { assignee: { select: { id: true, displayName: true, email: true } } },
        },
      },
    });
    if (!objective) {
      throw new BusinessException(
        PERFORMANCE_ERROR_CODES.COMMON_NOT_FOUND.message,
        PERFORMANCE_ERROR_CODES.COMMON_NOT_FOUND.code,
        PERFORMANCE_ERROR_CODES.COMMON_NOT_FOUND.httpStatus,
      );
    }
    return objective;
  }

  async create(data: {
    name: string;
    description?: string;
    cycleId: string;
    departmentId?: string;
    seq?: number;
    createdBy: string;
    assigneeIds?: string[];
  }) {
    const objective = await this.prisma.strategicObjective.create({
      data: {
        name: data.name,
        description: data.description,
        cycleId: data.cycleId,
        departmentId: data.departmentId,
        seq: data.seq ?? 0,
        createdBy: data.createdBy,
      },
    });

    // 创建时同时绑定负责人（去重，防止唯一键冲突）
    if (data.assigneeIds?.length) {
      const uniqueIds = [...new Set(data.assigneeIds)];
      await this.prisma.strategicObjectiveAssignment.createMany({
        data: uniqueIds.map((assigneeId) => ({
          objectiveId: objective.id,
          assigneeId,
        })),
        skipDuplicates: true,
      });
    }

    return this.findById(objective.id);
  }

  async update(id: string, data: {
    name?: string;
    description?: string;
    departmentId?: string;
    seq?: number;
  }) {
    await this.findById(id);
    return this.prisma.strategicObjective.update({
      where: { id },
      data,
    });
  }

  async delete(id: string) {
    await this.findById(id);
    await this.prisma.$transaction([
      this.prisma.strategicObjectiveAssignment.updateMany({
        where: { objectiveId: id, deletedAt: null },
        data: { deletedAt: new Date() },
      }),
      this.prisma.strategicObjective.update({
        where: { id },
        data: { deletedAt: new Date() },
      }),
    ]);
  }

  async assign(id: string, assigneeIds: string[]) {
    await this.findById(id);

    // 1. 软删除不在新列表中的现有分配
    await this.prisma.strategicObjectiveAssignment.updateMany({
      where: { objectiveId: id, deletedAt: null, assigneeId: { notIn: assigneeIds } },
      data: { deletedAt: new Date() },
    });

    // 2. 对每个新分配：恢复软删除行 或 创建新行
    for (const assigneeId of assigneeIds) {
      // 先尝试恢复已软删除的行（解决唯一约束冲突）
      const restored = await this.prisma.strategicObjectiveAssignment.updateMany({
        where: { objectiveId: id, assigneeId, deletedAt: { not: null } },
        data: { deletedAt: null },
      });
      // 如果没有可恢复的行，创建新行
      if (restored.count === 0) {
        await this.prisma.strategicObjectiveAssignment.upsert({
          where: { objectiveId_assigneeId: { objectiveId: id, assigneeId } },
          update: { deletedAt: null },
          create: { objectiveId: id, assigneeId },
        });
      }
    }

    return this.findById(id);
  }
}
