import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import {
  CreatePartGroupDto,
  UpdatePartGroupDto,
  QueryPartGroupsDto,
  AssignPartsToGroupDto,
  CreateGroupCustomFieldDto,
  UpdateGroupCustomFieldDto,
  PartGroupResponseDto,
  GroupCustomFieldResponseDto,
} from '../dto/part-group.dto';

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

  // ============================================
  // Part Group CRUD
  // ============================================

  /**
   * 创建零件分组
   */
  async createGroup(
    dto: CreatePartGroupDto,
    userId?: string,
  ): Promise<PartGroupResponseDto> {
    // 检查分组名称是否已存在
    const existingGroup = await this.prisma.partGroup.findUnique({
      where: { name: dto.name },
    });

    if (existingGroup) {
      throw new ConflictException(`Group with name "${dto.name}" already exists`);
    }

    // 创建分组和自定义字段
    const group = await this.prisma.partGroup.create({
      data: {
        name: dto.name,
        description: dto.description,
        displayOrder: dto.displayOrder ?? 0,
        isActive: dto.isActive ?? true,
        fieldsCount: dto.customFields?.length ?? 0,
        createdBy: userId,
        customFields: dto.customFields
          ? {
              create: dto.customFields.map((field, index) => ({
                key: field.key,
                nameEn: field.nameEn,  // 英文名称（必填）
                nameCn: field.nameCn,  // 中文名称（可选）
                type: field.type,
                required: field.required ?? false,
                visible: field.visible ?? true,
                editable: field.editable ?? true,
                searchable: field.searchable ?? true,
                options: field.options,
                validation: field.validation,
                description: field.description,
                placeholder: field.placeholder,
                helpText: field.helpText,
                displayOrder: field.displayOrder ?? index,
                createdBy: userId,
              })),
            }
          : undefined,
      },
      include: {
        customFields: {
          orderBy: { displayOrder: 'asc' },
        },
      },
    });

    return this.mapGroupToResponse(group);
  }

  /**
   * 获取所有分组
   */
  async findAllGroups(query: QueryPartGroupsDto): Promise<{
    data: PartGroupResponseDto[];
    total: number;
    page: number;
    limit: number;
  }> {
    const { search, isActive, page = 1, limit = 20 } = query;

    const where: any = {
      deletedAt: null,
    };

    if (search) {
      where.OR = [
        { name: { contains: search, mode: 'insensitive' } },
        { description: { contains: search, mode: 'insensitive' } },
      ];
    }

    if (isActive !== undefined) {
      where.isActive = isActive;
    }

    const [data, total] = await Promise.all([
      this.prisma.partGroup.findMany({
        where,
        include: {
          customFields: {
            where: { deletedAt: null },
            orderBy: { displayOrder: 'asc' },
          },
        },
        orderBy: [{ displayOrder: 'asc' }, { createdAt: 'desc' }],
        skip: (page - 1) * limit,
        take: limit,
      }),
      this.prisma.partGroup.count({ where }),
    ]);

    // 验证并修复每个分组的 partsCount
    await this.verifyAndFixPartsCounts(data);

    return {
      data: data.map((group) => this.mapGroupToResponse(group)),
      total,
      page,
      limit,
    };
  }

  /**
   * 获取单个分组详情
   */
  async findGroupById(id: string): Promise<PartGroupResponseDto> {
    const group = await this.prisma.partGroup.findUnique({
      where: { id },
      include: {
        customFields: {
          where: { deletedAt: null },
          orderBy: { displayOrder: 'asc' },
        },
      },
    });

    if (!group || group.deletedAt) {
      throw new NotFoundException(`Part group with ID "${id}" not found`);
    }

    return this.mapGroupToResponse(group);
  }

  /**
   * 更新分组
   */
  async updateGroup(
    id: string,
    dto: UpdatePartGroupDto,
    userId?: string,
  ): Promise<PartGroupResponseDto> {
    const existingGroup = await this.prisma.partGroup.findUnique({
      where: { id },
    });

    if (!existingGroup || existingGroup.deletedAt) {
      throw new NotFoundException(`Part group with ID "${id}" not found`);
    }

    // 如果更新名称，检查名称是否冲突
    if (dto.name && dto.name !== existingGroup.name) {
      const duplicateGroup = await this.prisma.partGroup.findUnique({
        where: { name: dto.name },
      });

      if (duplicateGroup && duplicateGroup.id !== id) {
        throw new ConflictException(`Group with name "${dto.name}" already exists`);
      }
    }

    const updatedGroup = await this.prisma.partGroup.update({
      where: { id },
      data: {
        ...dto,
        updatedBy: userId,
      },
      include: {
        customFields: {
          where: { deletedAt: null },
          orderBy: { displayOrder: 'asc' },
        },
      },
    });

    return this.mapGroupToResponse(updatedGroup);
  }

  /**
   * 删除分组（软删除）
   */
  async deleteGroup(id: string, userId?: string): Promise<void> {
    const existingGroup = await this.prisma.partGroup.findUnique({
      where: { id },
      include: {
        _count: {
          select: { parts: true },
        },
      },
    });

    if (!existingGroup || existingGroup.deletedAt) {
      throw new NotFoundException(`Part group with ID "${id}" not found`);
    }

    // 检查是否有零件使用该分组
    if (existingGroup._count.parts > 0) {
      throw new BadRequestException(
        `Cannot delete group "${existingGroup.name}" because it has ${existingGroup._count.parts} parts assigned`,
      );
    }

    await this.prisma.partGroup.update({
      where: { id },
      data: {
        deletedAt: new Date(),
        updatedBy: userId,
      },
    });
  }

  // ============================================
  // Custom Fields Management
  // ============================================

  /**
   * 添加自定义字段到分组
   */
  async addCustomFieldToGroup(
    groupId: string,
    dto: CreateGroupCustomFieldDto,
    userId?: string,
  ): Promise<GroupCustomFieldResponseDto> {
    const group = await this.prisma.partGroup.findUnique({
      where: { id: groupId },
    });

    if (!group || group.deletedAt) {
      throw new NotFoundException(`Part group with ID "${groupId}" not found`);
    }

    // 检查字段key是否已存在
    const existingField = await this.prisma.groupCustomField.findUnique({
      where: {
        groupId_key: {
          groupId,
          key: dto.key,
        },
      },
    });

    if (existingField && !existingField.deletedAt) {
      throw new ConflictException(
        `Field with key "${dto.key}" already exists in this group`,
      );
    }

    const field = await this.prisma.groupCustomField.create({
      data: {
        groupId,
        key: dto.key,
        nameEn: dto.nameEn,  // 英文名称（必填）
        nameCn: dto.nameCn,  // 中文名称（可选）
        type: dto.type,
        required: dto.required ?? false,
        visible: dto.visible ?? true,
        editable: dto.editable ?? true,
        searchable: dto.searchable ?? true,
        options: dto.options,
        validation: dto.validation,
        description: dto.description,
        placeholder: dto.placeholder,
        helpText: dto.helpText,
        displayOrder: dto.displayOrder ?? 0,
        createdBy: userId,
      },
    });

    // 更新分组的字段计数
    await this.prisma.partGroup.update({
      where: { id: groupId },
      data: {
        fieldsCount: { increment: 1 },
        updatedBy: userId,
      },
    });

    return this.mapFieldToResponse(field);
  }

  /**
   * 更新自定义字段
   */
  async updateCustomField(
    fieldId: string,
    dto: UpdateGroupCustomFieldDto,
    userId?: string,
  ): Promise<GroupCustomFieldResponseDto> {
    const existingField = await this.prisma.groupCustomField.findUnique({
      where: { id: fieldId },
    });

    if (!existingField || existingField.deletedAt) {
      throw new NotFoundException(`Custom field with ID "${fieldId}" not found`);
    }

    // 如果更新 key，检查是否冲突
    if (dto.key && dto.key !== existingField.key) {
      const duplicateField = await this.prisma.groupCustomField.findUnique({
        where: {
          groupId_key: {
            groupId: existingField.groupId,
            key: dto.key,
          },
        },
      });

      if (duplicateField && duplicateField.id !== fieldId) {
        throw new ConflictException(
          `Field with key "${dto.key}" already exists in this group`,
        );
      }
    }

    const updatedField = await this.prisma.groupCustomField.update({
      where: { id: fieldId },
      data: {
        ...dto,
        updatedBy: userId,
      },
    });

    return this.mapFieldToResponse(updatedField);
  }

  /**
   * 删除自定义字段（软删除）
   */
  async deleteCustomField(fieldId: string, userId?: string): Promise<void> {
    const existingField = await this.prisma.groupCustomField.findUnique({
      where: { id: fieldId },
    });

    if (!existingField || existingField.deletedAt) {
      throw new NotFoundException(`Custom field with ID "${fieldId}" not found`);
    }

    await this.prisma.groupCustomField.update({
      where: { id: fieldId },
      data: {
        deletedAt: new Date(),
        updatedBy: userId,
      },
    });

    // 更新分组的字段计数
    await this.prisma.partGroup.update({
      where: { id: existingField.groupId },
      data: {
        fieldsCount: { decrement: 1 },
        updatedBy: userId,
      },
    });
  }

  // ============================================
  // Part-Group Assignment
  // ============================================

  /**
   * 更新分组的零件计数
   */
  async updatePartsCount(groupId: string): Promise<void> {
    const count = await this.prisma.partGroupRelation.count({
      where: {
        groupId,
        part: {
          deletedAt: null,  // 只计算未删除的零件
        },
      },
    });

    await this.prisma.partGroup.update({
      where: { id: groupId },
      data: { partsCount: count },
    });
  }

  /**
   * 将零件分配到分组
   */
  async assignPartsToGroup(
    groupId: string,
    dto: AssignPartsToGroupDto,
    userId?: string,
  ): Promise<void> {
    const group = await this.prisma.partGroup.findUnique({
      where: { id: groupId },
    });

    if (!group || group.deletedAt) {
      throw new NotFoundException(`Part group with ID "${groupId}" not found`);
    }

    // 验证零件是否存在
    const parts = await this.prisma.part.findMany({
      where: {
        id: { in: dto.partIds },
        deletedAt: null,
      },
    });

    if (parts.length !== dto.partIds.length) {
      throw new BadRequestException('Some parts not found or have been deleted');
    }

    // 创建关联（使用 createMany 跳过已存在的关联）
    await this.prisma.partGroupRelation.createMany({
      data: dto.partIds.map((partId) => ({
        partId,
        groupId,
        createdBy: userId,
      })),
      skipDuplicates: true,
    });

    // 更新分组的零件计数
    const count = await this.prisma.partGroupRelation.count({
      where: { groupId },
    });

    await this.prisma.partGroup.update({
      where: { id: groupId },
      data: {
        partsCount: count,
        updatedBy: userId,
      },
    });
  }

  /**
   * 从分组中移除零件
   */
  async removePartsFromGroup(
    groupId: string,
    dto: AssignPartsToGroupDto,
    userId?: string,
  ): Promise<void> {
    const group = await this.prisma.partGroup.findUnique({
      where: { id: groupId },
    });

    if (!group || group.deletedAt) {
      throw new NotFoundException(`Part group with ID "${groupId}" not found`);
    }

    await this.prisma.partGroupRelation.deleteMany({
      where: {
        groupId,
        partId: { in: dto.partIds },
      },
    });

    // 更新分组的零件计数
    const count = await this.prisma.partGroupRelation.count({
      where: { groupId },
    });

    await this.prisma.partGroup.update({
      where: { id: groupId },
      data: {
        partsCount: count,
        updatedBy: userId,
      },
    });
  }

  /**
   * 获取分组的所有零件
   */
  async getGroupParts(groupId: string, page = 1, limit = 20) {
    const group = await this.prisma.partGroup.findUnique({
      where: { id: groupId },
    });

    if (!group || group.deletedAt) {
      throw new NotFoundException(`Part group with ID "${groupId}" not found`);
    }

    const [data, total] = await Promise.all([
      this.prisma.part.findMany({
        where: {
          groups: {
            some: { groupId },
          },
          deletedAt: null,
        },
        skip: (page - 1) * limit,
        take: limit,
      }),
      this.prisma.part.count({
        where: {
          groups: {
            some: { groupId },
          },
          deletedAt: null,
        },
      }),
    ]);

    return {
      data,
      total,
      page,
      limit,
    };
  }

  // ============================================
  // Helper Methods
  // ============================================

  /**
   * 验证并修复分组的零件计数
   * 每次获取分组列表时自动调用，确保计数准确
   */
  private async verifyAndFixPartsCounts(groups: any[]): Promise<void> {
    const updates: Promise<any>[] = [];

    for (const group of groups) {
      // 计算实际的零件数量（只计算未删除的零件）
      const actualCount = await this.prisma.partGroupRelation.count({
        where: {
          groupId: group.id,
          part: {
            deletedAt: null,
          },
        },
      });

      // 如果计数不匹配，更新数据库
      if (actualCount !== group.partsCount) {
        console.log(
          `[PartsCount] Fixing group "${group.name}": ${group.partsCount} → ${actualCount}`,
        );
        
        updates.push(
          this.prisma.partGroup.update({
            where: { id: group.id },
            data: { partsCount: actualCount },
          }),
        );

        // 立即更新内存中的值，以便返回正确的数据
        group.partsCount = actualCount;
      }
    }

    // 批量执行所有更新
    if (updates.length > 0) {
      await Promise.all(updates);
      console.log(`[PartsCount] Fixed ${updates.length} group(s)`);
    }
  }

  private mapGroupToResponse(group: any): PartGroupResponseDto {
    return {
      id: group.id,
      name: group.name,
      description: group.description,
      displayOrder: group.displayOrder,
      isActive: group.isActive,
      partsCount: group.partsCount,
      fieldsCount: group.fieldsCount,
      customFields: group.customFields?.map((field: any) => this.mapFieldToResponse(field)),
      createdAt: group.createdAt,
      updatedAt: group.updatedAt,
    };
  }

  private mapFieldToResponse(field: any): GroupCustomFieldResponseDto {
    return {
      id: field.id,
      groupId: field.groupId,
      key: field.key,
      nameEn: field.nameEn,  // 英文名称（必填）
      nameCn: field.nameCn,  // 中文名称（可选）
      type: field.type,
      required: field.required,
      visible: field.visible,
      editable: field.editable,
      searchable: field.searchable,
      options: field.options,
      validation: field.validation,
      description: field.description,
      placeholder: field.placeholder,
      helpText: field.helpText,
      displayOrder: field.displayOrder,
      createdAt: field.createdAt,
      updatedAt: field.updatedAt,
    };
  }
}

