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';

/**
 * 360 评估模板服务
 * 负责 360 评估模板的 CRUD 管理
 */
@Injectable()
export class Evaluation360TemplateService {
  constructor(private readonly prisma: PrismaService) {}

  // ==================== CRUD ====================

  async findAll(query?: { organizationId?: string }) {
    const { organizationId } = query || {};

    const where: any = { deletedAt: null, isActive: true };
    if (organizationId) where.organizationId = organizationId;

    const items = await this.prisma.evaluation360Template.findMany({
      where,
      orderBy: [{ isDefault: 'desc' }, { createdAt: 'desc' }],
    });

    return { items };
  }

  async findById(id: string) {
    const template = await this.prisma.evaluation360Template.findFirst({
      where: { id, deletedAt: null },
    });

    if (!template) {
      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 template;
  }

  async create(
    data: {
      name: string;
      description?: string;
      dimensions: any[];
      relationshipTypes: string[];
      isDefault?: boolean;
      organizationId?: string;
      cycleId?: string;
      scope?: any;
    },
    userId: string,
  ) {
    // 如果设为默认，先取消其他默认
    if (data.isDefault) {
      await this.prisma.evaluation360Template.updateMany({
        where: { isDefault: true, deletedAt: null },
        data: { isDefault: false },
      });
    }

    return this.prisma.evaluation360Template.create({
      data: {
        name: data.name,
        description: data.description,
        dimensions: data.dimensions as any,
        relationshipTypes: data.relationshipTypes as any,
        isDefault: data.isDefault ?? false,
        isActive: true,
        createdBy: userId,
        organizationId: data.organizationId,
        cycleId: data.cycleId,
        scope: data.scope ?? undefined,
      },
    });
  }

  async update(
    id: string,
    data: {
      name?: string;
      description?: string;
      dimensions?: any[];
      relationshipTypes?: string[];
      isDefault?: boolean;
      isActive?: boolean;
      organizationId?: string;
      cycleId?: string;
      scope?: any;
    },
  ) {
    await this.findById(id);

    // 如果设为默认，先取消其他默认（与 create/setDefault 一致）
    if (data.isDefault) {
      await this.prisma.evaluation360Template.updateMany({
        where: { isDefault: true, deletedAt: null, id: { not: id } },
        data: { isDefault: false },
      });
    }

    const { cycleId, scope, ...rest } = data;
    return this.prisma.evaluation360Template.update({
      where: { id },
      data: {
        ...rest,
        dimensions: rest.dimensions as any,
        relationshipTypes: rest.relationshipTypes as any,
        ...(cycleId !== undefined ? { cycleId } : {}),
        ...(scope !== undefined ? { scope } : {}),
      },
    });
  }

  /**
   * 根据用户信息匹配适用的模板
   * 优先级：cycleId 精确匹配 > scope 匹配 > isDefault 兜底
   */
  async findApplicable(userId: string, cycleId?: string) {
    const templates = await this.prisma.evaluation360Template.findMany({
      where: { deletedAt: null, isActive: true },
      orderBy: [{ isDefault: 'desc' }, { createdAt: 'desc' }],
    });

    if (templates.length === 0) return null;

    // 查用户的部门和职级信息
    const userDepts = await this.prisma.userDepartment.findMany({
      where: { userId, leftAt: null },
      select: { departmentId: true, positionId: true },
    });
    const userDeptIds = userDepts.map((d) => d.departmentId);

    // 查用户职位等级（取最高）
    let userLevel: number | null = null;
    const positionIds = userDepts.map((d) => d.positionId).filter(Boolean) as string[];
    if (positionIds.length > 0) {
      const positions = await this.prisma.position.findMany({
        where: { id: { in: positionIds } },
        select: { level: true },
      });
      userLevel = positions.reduce((max, p) => Math.max(max, p.level ?? 0), 0) || null;
    }

    // 匹配逻辑
    let matched: typeof templates[0] | null = null;

    for (const tpl of templates) {
      // 1. cycleId 精确匹配
      if (cycleId && tpl.cycleId === cycleId) {
        if (this.matchesScope(tpl.scope as any, userDeptIds, userLevel, userId)) {
          return tpl;
        }
      }
    }

    // 2. scope 匹配（无 cycleId 限定或 cycleId 为空的模板）
    for (const tpl of templates) {
      if (tpl.cycleId) continue; // 跳过绑定了特定周期的
      if (this.matchesScope(tpl.scope as any, userDeptIds, userLevel, userId)) {
        matched = tpl;
        break;
      }
    }

    // 3. 兜底：返回默认模板
    return matched || templates.find((t) => t.isDefault) || templates[0];
  }

  private matchesScope(
    scope: { scopeType: string; departmentIds?: string[]; minLevel?: number; userIds?: string[] } | null,
    userDeptIds: string[],
    userLevel: number | null,
    userId: string,
  ): boolean {
    if (!scope || scope.scopeType === 'ALL') return true;

    switch (scope.scopeType) {
      case 'DEPARTMENT':
        return scope.departmentIds?.some((id) => userDeptIds.includes(id)) ?? false;
      case 'LEVEL':
        return userLevel != null && scope.minLevel != null && userLevel >= scope.minLevel;
      case 'CUSTOM':
        return scope.userIds?.includes(userId) ?? false;
      default:
        return true;
    }
  }

  async delete(id: string) {
    const template = await this.findById(id);

    if (template.isDefault) {
      throw new BusinessException(
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.message,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.code,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.httpStatus,
        { reason: 'template_is_default' },
      );
    }

    await this.prisma.evaluation360Template.update({
      where: { id },
      data: { deletedAt: new Date(), isActive: false },
    });

    return { success: true };
  }

  async setDefault(id: string) {
    const template = await this.findById(id);

    if (!template.isActive) {
      throw new BusinessException(
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.message,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.code,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.httpStatus,
        { reason: 'template_inactive' },
      );
    }

    await this.prisma.$transaction([
      this.prisma.evaluation360Template.updateMany({
        where: { isDefault: true, deletedAt: null },
        data: { isDefault: false },
      }),
      this.prisma.evaluation360Template.update({
        where: { id },
        data: { isDefault: true },
      }),
    ]);

    return this.findById(id);
  }
}
