import {
  Injectable,
  NotFoundException,
  BadRequestException,
  ConflictException,
  forwardRef,
  Inject,
  Logger,
} from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { Prisma, PartStatus, StockAlertType, AlertSeverity } from '@prisma/client';
import {
  CreatePartDto,
  UpdatePartDto,
  QueryPartsDto,
  BulkImportPartsDto,
  StockStatus,
} from '../dto/part.dto';
import { PartGroupsService } from './part-groups.service';

@Injectable()
export class PartsService {
  private readonly logger = new Logger(PartsService.name);

  constructor(
    private readonly prisma: PrismaService,
    @Inject(forwardRef(() => PartGroupsService))
    private readonly partGroupsService: PartGroupsService,
  ) {}

  /**
   * 计算库存状态
   */
  private calculateStockStatus(part: { currentStock: number; minStock: number }): StockStatus {
    if (part.currentStock <= 0) {
      return StockStatus.OUT_OF_STOCK;
    }
    if (part.currentStock <= part.minStock) {
      return StockStatus.LOW;
    }
    return StockStatus.NORMAL;
  }

  /**
   * 统一标识符解析
   * 支持 UUID、零件编号、二维码、条码
   */
  private async resolvePartIdentifier(identifier: string) {
    // 1. 尝试 UUID（最高优先级）
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (uuidRegex.test(identifier)) {
      const part = await this.prisma.part.findUnique({
        where: { id: identifier, deletedAt: null },
        include: {
          labels: true,
          stockAlerts: {
            where: { status: 'PENDING' },
            orderBy: { createdAt: 'desc' },
            take: 10,
          },
          inventoryLogs: {
            orderBy: { createdAt: 'desc' },
            take: 20,
          },
          groups: {
            include: {
              group: {
                include: {
                  customFields: {
                    where: { deletedAt: null },
                    orderBy: { displayOrder: 'asc' },
                  },
                },
              },
            },
          },
          warehouse: {
            select: { id: true, code: true, nameEn: true, nameCn: true },
          },
          storageLocation: {
            select: { id: true, code: true, nameEn: true, nameCn: true, zone: true },
          },
          _count: {
            select: {
              inventoryLogs: true,
              labels: true,
              stockAlerts: true,
            },
          },
        },
      });
      if (part) {
        return {
          ...part,
          stockStatus: this.calculateStockStatus(part),
        };
      }
    }

    // 2. 尝试零件编号
    let part = await this.prisma.part.findFirst({
      where: { partNumber: identifier, deletedAt: null },
      include: {
        labels: true,
        stockAlerts: {
          where: { status: 'PENDING' },
        },
        groups: {
          include: {
            group: {
              include: {
                customFields: {
                  where: { deletedAt: null },
                  orderBy: { displayOrder: 'asc' },
                },
              },
            },
          },
        },
        warehouse: {
          select: { id: true, code: true, nameEn: true, nameCn: true },
        },
        storageLocation: {
          select: { id: true, code: true, nameEn: true, nameCn: true, zone: true },
        },
      },
    });
    if (part) {
      return {
        ...part,
        stockStatus: this.calculateStockStatus(part),
      };
    }

    // 3. 未找到
    throw new NotFoundException(`Part '${identifier}' not found`);
  }

  /**
   * 创建零件
   */
  async create(createPartDto: CreatePartDto, userId: string) {
    // 检查 Part Number 是否已存在
    // 注意：part_number 在数据库有唯一约束，此处检查是为了提供更友好的错误消息
    const existing = await this.prisma.part.findFirst({
      where: { 
        partNumber: createPartDto.partNumber,
      },
    });

    if (existing) {
      throw new ConflictException(
        `Part with number ${createPartDto.partNumber} already exists`,
      );
    }

    // 提取 groupIds 和 customFields
    const { groupIds, customFields, ...partData } = createPartDto;

    const part = await this.prisma.part.create({
      data: {
        ...partData,
        currentStock: createPartDto.currentStock ?? 0,
        minStock: createPartDto.minStock ?? 0,
        unit: createPartDto.unit ?? 'pcs',
        status: createPartDto.status ?? PartStatus.ACTIVE,
        customFields: customFields || {},
      },
      include: {
        labels: true,
        stockAlerts: {
          where: { status: 'PENDING' },
          orderBy: { createdAt: 'desc' },
          take: 5,
        },
        groups: {
          include: {
            group: true,
          },
        },
      },
    });

    // 创建分组关联
    if (groupIds && groupIds.length > 0) {
      await this.prisma.partGroupRelation.createMany({
        data: groupIds.map(groupId => ({
          partId: part.id,
          groupId,
          createdBy: userId,
        })),
      });

      // 更新每个分组的零件计数
      for (const groupId of groupIds) {
        await this.partGroupsService.updatePartsCount(groupId);
      }
    }

    // 检查库存并创建告警
    await this.checkStockAndCreateAlerts(part.id);

    return part;
  }

  /**
   * 查询零件列表
   */
  async findAll(query: QueryPartsDto) {
    const {
      search,
      partNumber,
      partNameEn,
      category,
      station,
      warehouseLocation,
      status,
      stockStatus,  // 新增：库存状态筛选
      lowStock,
      outOfStock,
      groupIds,
      page = 1,
      limit = 20,
      sortBy = 'createdAt',
      sortOrder = 'desc',
    } = query;
    
    this.logger.log(`[findAll] Received groupIds: ${JSON.stringify(groupIds)}, type: ${typeof groupIds}`);

    const where: Prisma.PartWhereInput = {
      deletedAt: null,
    };

    // 分组筛选
    if (groupIds && groupIds.length > 0) {
      where.groups = {
        some: {
          groupId: {
            in: groupIds,
          },
        },
      };
    }

    // 搜索条件
    if (search) {
      where.OR = [
        { partNumber: { contains: search, mode: 'insensitive' } },
        { partNameEn: { contains: search, mode: 'insensitive' } },
        { partNameCn: { contains: search, mode: 'insensitive' } },
        { specifications: { contains: search, mode: 'insensitive' } },
        { remark: { contains: search, mode: 'insensitive' } },
      ];
    }

    if (partNumber) {
      // 精确匹配零件编号（用于验证重复）
      where.partNumber = partNumber;
    }

    if (partNameEn) {
      where.partNameEn = { contains: partNameEn, mode: 'insensitive' };
    }

    if (station) {
      where.station = station;
    }

    if (warehouseLocation) {
      where.warehouseLocation = warehouseLocation;
    }

    if (status) {
      where.status = status;
    }

    // 库存状态筛选（新增）
    if (stockStatus) {
      switch (stockStatus) {
        case StockStatus.OUT_OF_STOCK:
          where.currentStock = { lte: 0 };
          break;
        case StockStatus.LOW:
          where.AND = [
            ...(Array.isArray(where.AND) ? where.AND : []),
            {
              currentStock: { gt: 0 },
            },
          ];
          // 注意：需要在后处理中过滤 currentStock <= minStock
          break;
        case StockStatus.NORMAL:
          // 需要在后处理中过滤 currentStock > minStock
          break;
      }
    }

    // 低库存筛选（保留向后兼容）
    if (lowStock) {
      where.AND = [
        ...(Array.isArray(where.AND) ? where.AND : []),
        {
          currentStock: {
            lte: this.prisma.part.fields.minStock,
          },
        },
      ];
    }

    // 零库存筛选（保留向后兼容）
    if (outOfStock) {
      where.currentStock = 0;
    }

    const skip = (page - 1) * limit;

    const [items, total] = await Promise.all([
      this.prisma.part.findMany({
        where,
        skip,
        take: limit,
        orderBy: { [sortBy]: sortOrder },
        include: {
          labels: {
            where: { status: 'ACTIVE' },
            take: 1,
            orderBy: { createdAt: 'desc' },
          },
          stockAlerts: {
            where: { status: 'PENDING' },
            orderBy: { createdAt: 'desc' },
            take: 1,
          },
          groups: {
            include: {
              group: {
                include: {
                  customFields: {
                    where: { deletedAt: null },
                    orderBy: { displayOrder: 'asc' },
                  },
                },
              },
            },
          },
          _count: {
            select: {
              inventoryLogs: true,
              labels: true,
            },
          },
        },
      }),
      this.prisma.part.count({ where }),
    ]);

    const totalPages = Math.ceil(total / limit);

    // 为每个零件添加 stockStatus 计算字段
    let itemsWithStockStatus = items.map(item => ({
      ...item,
      stockStatus: this.calculateStockStatus(item),
    }));

    // 如果有 stockStatus 筛选，需要后处理过滤（因为无法在 SQL 中直接比较两个字段）
    if (stockStatus === StockStatus.LOW) {
      itemsWithStockStatus = itemsWithStockStatus.filter(
        item => item.currentStock > 0 && item.currentStock <= item.minStock
      );
    } else if (stockStatus === StockStatus.NORMAL) {
      itemsWithStockStatus = itemsWithStockStatus.filter(
        item => item.currentStock > item.minStock
      );
    }

    return {
      items: itemsWithStockStatus,
      total: stockStatus ? itemsWithStockStatus.length : total,  // 如果有后处理筛选，更新 total
      page,
      limit,
      totalPages,
      hasNext: page < totalPages,
      hasPrev: page > 1,
    };
  }

  /**
   * 获取零件详情
   */
  async findOne(id: string) {
    const part = await this.prisma.part.findUnique({
      where: { id },
      include: {
        labels: {
          orderBy: { createdAt: 'desc' },
        },
        stockAlerts: {
          orderBy: { createdAt: 'desc' },
          take: 10,
        },
        inventoryLogs: {
          orderBy: { createdAt: 'desc' },
          take: 20,
        },
        groups: {
          include: {
            group: {
              include: {
                  customFields: {
                    where: { deletedAt: null },
                    orderBy: { displayOrder: 'asc' },
                  },
              },
            },
          },
        },
        _count: {
          select: {
            inventoryLogs: true,
            labels: true,
            stockAlerts: true,
          },
        },
      },
    });

    if (!part) {
      throw new NotFoundException(`Part with ID ${id} not found`);
    }

    // 添加 stockStatus 计算字段
    return {
      ...part,
      stockStatus: this.calculateStockStatus(part),
    };
  }

  /**
   * 通过统一标识符查询零件
   * 支持 UUID、零件编号、二维码、条码
   */
  async findByIdentifier(identifier: string) {
    return this.resolvePartIdentifier(identifier);
  }

  /**
   * 通过 Part Number 查询零件（保留用于向后兼容）
   * @deprecated 请使用 findByIdentifier 代替
   */
  async findByPartNumber(partNumber: string) {
    return this.findByIdentifier(partNumber);
  }

  /**
   * 通过 QR Code 或 Barcode 查询零件（保留用于向后兼容）
   * @deprecated 请使用 findByIdentifier 代替
   */
  async findByCode(code: string) {
    return this.findByIdentifier(code);
  }

  /**
   * 通过统一标识符更新零件
   */
  async updateByIdentifier(identifier: string, updatePartDto: UpdatePartDto, userId: string) {
    // 先解析标识符获取零件
    const part = await this.resolvePartIdentifier(identifier);
    return this.update(part.id, updatePartDto, userId);
  }

  /**
   * 更新零件（通过ID）
   */
  async update(id: string, updatePartDto: UpdatePartDto, userId: string) {
    // 检查零件是否存在
    const existing = await this.prisma.part.findUnique({
      where: { id },
      include: {
        groups: true,
      },
    });
    if (!existing) {
      throw new NotFoundException(`Part with ID ${id} not found`);
    }

    // 如果更新 Part Number，检查是否重复
    // 注意：part_number 在数据库有唯一约束，此处检查是为了提供更友好的错误消息
    if (updatePartDto.partNumber) {
      const duplicate = await this.prisma.part.findFirst({
        where: { 
          partNumber: updatePartDto.partNumber,
          id: { not: id },  // 排除当前零件自己
        },
      });
      if (duplicate) {
        throw new ConflictException(
          `Part with number ${updatePartDto.partNumber} already exists`,
        );
      }
    }

    // 提取 groupIds，不传给 part update
    const { groupIds, ...partUpdateData } = updatePartDto;

    const updated = await this.prisma.part.update({
      where: { id },
      data: partUpdateData,
      include: {
        labels: true,
        stockAlerts: {
          where: { status: 'PENDING' },
        },
      },
    });

    // 处理分组关系更新
    if (groupIds !== undefined) {
      // 获取旧的分组ID
      const oldGroupIds = existing.groups.map(g => g.groupId);

      // 删除所有现有的分组关系
      await this.prisma.partGroupRelation.deleteMany({
        where: { partId: id },
      });

      // 创建新的分组关系
      if (groupIds.length > 0) {
        await this.prisma.partGroupRelation.createMany({
          data: groupIds.map(groupId => ({
            partId: id,
            groupId,
            createdBy: userId,
          })),
        });
      }

      // 更新受影响的分组的零件计数（包括旧分组和新分组）
      const affectedGroupIds = new Set([...oldGroupIds, ...groupIds]);
      for (const groupId of affectedGroupIds) {
        const count = await this.prisma.partGroupRelation.count({
          where: { 
            groupId,
            part: { deletedAt: null },
          },
        });
        await this.prisma.partGroup.update({
          where: { id: groupId },
          data: { partsCount: count },
        });
      }
    }

    // 如果更新了库存阈值，重新检查告警
    if (updatePartDto.minStock !== undefined || updatePartDto.maxStock !== undefined) {
      await this.checkStockAndCreateAlerts(id);
    }

    return updated;
  }

  /**
   * 删除零件（软删除）
   */
  /**
   * 通过统一标识符删除零件
   */
  async removeByIdentifier(identifier: string, userId: string) {
    // 先解析标识符获取零件
    const part = await this.resolvePartIdentifier(identifier);
    return this.remove(part.id, userId);
  }

  /**
   * 删除零件（通过ID）
   */
  async remove(id: string, userId: string) {
    const part = await this.prisma.part.findUnique({
      where: { id },
      include: {
        groups: true,
      },
    });
    if (!part) {
      throw new NotFoundException(`Part with ID ${id} not found`);
    }

    // 获取零件所属的分组ID
    const groupIds = part.groups.map(g => g.groupId);

    // 软删除：修改 part_number 以避免唯一约束冲突
    // 格式：原编号_deleted_时间戳_UUID前8位
    const deletedPartNumber = `${part.partNumber}_deleted_${Date.now()}_${id.substring(0, 8)}`;

    await this.prisma.part.update({
      where: { id },
      data: {
        deletedAt: new Date(),
        status: PartStatus.INACTIVE,
        partNumber: deletedPartNumber, // 修改编号以释放唯一约束
      },
    });

    // 更新每个分组的零件计数
    if (groupIds.length > 0) {
      for (const groupId of groupIds) {
        const count = await this.prisma.partGroupRelation.count({
          where: { 
            groupId,
            part: { deletedAt: null }, // 只计算未删除的零件
          },
        });
        await this.prisma.partGroup.update({
          where: { id: groupId },
          data: { partsCount: count },
        });
      }
    }

    return { message: 'Part deleted successfully' };
  }

  /**
   * 批量导入零件
   */
  async bulkImport(
    bulkImportDto: BulkImportPartsDto,
    userId: string,
    userName: string,
  ) {
    const { parts, updateExisting = false, skipErrors = true } = bulkImportDto;

    const results = {
      total: parts.length,
      success: 0,
      failed: 0,
      updated: 0,
      errors: [] as any[],
    };

    for (const partDto of parts) {
      try {
        const existing = await this.prisma.part.findFirst({
          where: { 
            partNumber: partDto.partNumber,
            deletedAt: null 
          },
        });

        if (existing) {
          if (updateExisting) {
            await this.update(existing.id, partDto, userId);
            results.updated++;
            results.success++;
          } else {
            if (!skipErrors) {
              throw new ConflictException(
                `Part ${partDto.partNumber} already exists`,
              );
            }
            results.failed++;
            results.errors.push({
              partNumber: partDto.partNumber,
              error: 'Part already exists',
            });
          }
        } else {
          await this.create(partDto, userId);
          results.success++;
        }
      } catch (error) {
        results.failed++;
        results.errors.push({
          partNumber: partDto.partNumber,
          error: error.message,
        });

        if (!skipErrors) {
          throw error;
        }
      }
    }

    return results;
  }

  /**
   * 获取库存统计
   */
  async getInventoryStats(query?: {
    station?: string;
    warehouseLocation?: string;
    category?: string;
  }) {
    const where: Prisma.PartWhereInput = {
      deletedAt: null,
      status: PartStatus.ACTIVE,
    };

    if (query?.station) {
      where.station = query.station;
    }

    if (query?.warehouseLocation) {
      where.warehouseLocation = query.warehouseLocation;
    }

    const [
      totalParts,
      lowStockParts,
      outOfStockParts,
      totalValue,
      stationStats,
    ] = await Promise.all([
      // 总零件数
      this.prisma.part.count({ where }),

      // 低库存零件数
      this.prisma.part.count({
        where: {
          ...where,
          currentStock: {
            lte: this.prisma.part.fields.minStock,
          },
        },
      }),

      // 零库存零件数
      this.prisma.part.count({
        where: {
          ...where,
          currentStock: 0,
        },
      }),

      // 总库存价值
      this.prisma.part.aggregate({
        where,
        _sum: {
          currentStock: true,
        },
      }),

      // 按工位统计
      this.prisma.part.groupBy({
        by: ['station'],
        where: {
          ...where,
          station: { not: null },
        },
        _count: true,
        _sum: {
          currentStock: true,
        },
      }),
    ]);

    return {
      totalParts,
      activeParts: totalParts, // ACTIVE 状态的零件数（与 totalParts 相同，因为 where 条件已经过滤了 ACTIVE）
      lowStockParts,
      outOfStockParts,
      totalStock: totalValue._sum.currentStock || 0,
      stationStats,
    };
  }

  /**
   * 获取所有分类（已废弃 - category 字段已移除）
   * 现在分类通过 PartGroup 管理
   */
  async getCategories() {
    // 返回空数组，实际分类功能由 PartGroup 提供
    return [];
  }

  /**
   * 获取所有工位
   */
  async getStations() {
    const stations = await this.prisma.part.findMany({
      where: {
        deletedAt: null,
        station: { not: null },
      },
      select: { station: true },
      distinct: ['station'],
    });

    return stations
      .map((s) => s.station)
      .filter((s) => s !== null)
      .sort();
  }

  /**
   * 获取所有仓位
   */
  async getWarehouseLocations() {
    const locations = await this.prisma.part.findMany({
      where: {
        deletedAt: null,
        warehouseLocation: { not: null },
      },
      select: { warehouseLocation: true },
      distinct: ['warehouseLocation'],
    });

    return locations
      .map((l) => l.warehouseLocation)
      .filter((l) => l !== null)
      .sort();
  }

  /**
   * 检查库存并创建告警
   */
  async checkStockAndCreateAlerts(partId: string) {
    const part = await this.prisma.part.findUnique({
      where: { id: partId },
    });

    if (!part) return;

    const { currentStock, minStock, maxStock } = part;

    // 清除旧的告警
    await this.prisma.stockAlert.updateMany({
      where: {
        partId,
        status: 'PENDING',
      },
      data: {
        status: 'RESOLVED',
        resolvedAt: new Date(),
        resolution: 'Auto-resolved by system',
      },
    });

    // 零库存告警
    if (currentStock === 0) {
      await this.prisma.stockAlert.create({
        data: {
          partId,
          alertType: StockAlertType.OUT_OF_STOCK,
          severity: AlertSeverity.CRITICAL,
          currentStock,
          threshold: 0,
          message: `Part ${part.partNumber} is out of stock`,
        },
      });
    }
    // 低库存告警
    else if (currentStock <= minStock) {
      await this.prisma.stockAlert.create({
        data: {
          partId,
          alertType: StockAlertType.LOW_STOCK,
          severity: AlertSeverity.HIGH,
          currentStock,
          threshold: minStock,
          message: `Part ${part.partNumber} stock is below minimum (${currentStock}/${minStock})`,
        },
      });
    }
    // 接近最小库存告警
    else if (currentStock <= minStock * 1.2) {
      await this.prisma.stockAlert.create({
        data: {
          partId,
          alertType: StockAlertType.APPROACHING_MIN,
          severity: AlertSeverity.MEDIUM,
          currentStock,
          threshold: minStock,
          message: `Part ${part.partNumber} stock is approaching minimum (${currentStock}/${minStock})`,
        },
      });
    }

    // 超库存告警
    if (maxStock && currentStock > maxStock) {
      await this.prisma.stockAlert.create({
        data: {
          partId,
          alertType: StockAlertType.OVERSTOCK,
          severity: AlertSeverity.LOW,
          currentStock,
          threshold: maxStock,
          message: `Part ${part.partNumber} stock exceeds maximum (${currentStock}/${maxStock})`,
        },
      });
    }
  }
}

