import {
  Injectable,
  NotFoundException,
} from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { Prisma, AlertStatus } from '@prisma/client';
import {
  QueryStockAlertsDto,
  AcknowledgeAlertDto,
  ResolveAlertDto,
} from '../dto/inventory.dto';

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

  /**
   * 查询库存告警
   */
  async findAll(query: QueryStockAlertsDto) {
    const {
      partId,
      alertType,
      severity,
      status,
      page = 1,
      limit = 20,
      sortBy = 'createdAt',
      sortOrder = 'desc',
    } = query;

    const where: Prisma.StockAlertWhereInput = {};

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

    if (alertType) {
      where.alertType = alertType as any;
    }

    if (severity) {
      where.severity = severity as any;
    }

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

    const skip = (page - 1) * limit;

    const [items, total] = await Promise.all([
      this.prisma.stockAlert.findMany({
        where,
        skip,
        take: limit,
        orderBy: { [sortBy]: sortOrder },
        include: {
          part: {
            select: {
              id: true,
              partNumber: true,
              partNameEn: true,
              partNameCn: true,
              currentStock: true,
              minStock: true,
              maxStock: true,
              station: true,
              warehouseLocation: true,
            },
          },
        },
      }),
      this.prisma.stockAlert.count({ where }),
    ]);

    return {
      items,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 获取告警详情
   */
  async findOne(id: string) {
    const alert = await this.prisma.stockAlert.findUnique({
      where: { id },
      include: {
        part: true,
      },
    });

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

    return alert;
  }

  /**
   * 确认告警
   */
  async acknowledge(
    acknowledgeDto: AcknowledgeAlertDto,
    userId: string,
    userName: string,
  ) {
    const { alertId, note } = acknowledgeDto;

    const alert = await this.prisma.stockAlert.findUnique({
      where: { id: alertId },
    });

    if (!alert) {
      throw new NotFoundException(`Alert with ID ${alertId} not found`);
    }

    const updated = await this.prisma.stockAlert.update({
      where: { id: alertId },
      data: {
        status: AlertStatus.ACKNOWLEDGED,
        acknowledgedBy: userName,
        acknowledgedAt: new Date(),
      },
      include: {
        part: true,
      },
    });

    return {
      alert: updated,
      message: 'Alert acknowledged successfully',
    };
  }

  /**
   * 解决告警
   */
  async resolve(
    resolveDto: ResolveAlertDto,
    userId: string,
    userName: string,
  ) {
    const { alertId, resolution, newStock } = resolveDto;

    const alert = await this.prisma.stockAlert.findUnique({
      where: { id: alertId },
      include: {
        part: true,
      },
    });

    if (!alert) {
      throw new NotFoundException(`Alert with ID ${alertId} not found`);
    }

    // 如果提供了新库存，更新零件库存
    if (newStock !== undefined && newStock !== null) {
      await this.prisma.part.update({
        where: { id: alert.partId },
        data: { currentStock: newStock },
      });
    }

    const updated = await this.prisma.stockAlert.update({
      where: { id: alertId },
      data: {
        status: AlertStatus.RESOLVED,
        resolvedBy: userName,
        resolvedAt: new Date(),
        resolution,
      },
      include: {
        part: true,
      },
    });

    return {
      alert: updated,
      message: 'Alert resolved successfully',
    };
  }

  /**
   * 批量确认告警
   */
  async bulkAcknowledge(alertIds: string[], userId: string, userName: string) {
    const result = await this.prisma.stockAlert.updateMany({
      where: {
        id: { in: alertIds },
        status: AlertStatus.PENDING,
      },
      data: {
        status: AlertStatus.ACKNOWLEDGED,
        acknowledgedBy: userName,
        acknowledgedAt: new Date(),
      },
    });

    return {
      updated: result.count,
      message: `${result.count} alert(s) acknowledged successfully`,
    };
  }

  /**
   * 批量解决告警
   */
  async bulkResolve(
    alertIds: string[],
    resolution: string,
    userId: string,
    userName: string,
  ) {
    const result = await this.prisma.stockAlert.updateMany({
      where: {
        id: { in: alertIds },
        status: { in: [AlertStatus.PENDING, AlertStatus.ACKNOWLEDGED] },
      },
      data: {
        status: AlertStatus.RESOLVED,
        resolvedBy: userName,
        resolvedAt: new Date(),
        resolution,
      },
    });

    return {
      updated: result.count,
      message: `${result.count} alert(s) resolved successfully`,
    };
  }

  /**
   * 获取告警统计
   */
  async getStats() {
    const [
      totalAlerts,
      pendingAlerts,
      acknowledgedAlerts,
      resolvedAlerts,
      alertsBySeverity,
      alertsByType,
      topAlertedParts,
    ] = await Promise.all([
      // 总告警数
      this.prisma.stockAlert.count(),

      // 待处理告警
      this.prisma.stockAlert.count({
        where: { status: AlertStatus.PENDING },
      }),

      // 已确认告警
      this.prisma.stockAlert.count({
        where: { status: AlertStatus.ACKNOWLEDGED },
      }),

      // 已解决告警
      this.prisma.stockAlert.count({
        where: { status: AlertStatus.RESOLVED },
      }),

      // 按严重程度统计
      this.prisma.stockAlert.groupBy({
        by: ['severity'],
        where: { status: { in: [AlertStatus.PENDING, AlertStatus.ACKNOWLEDGED] } },
        _count: true,
      }),

      // 按类型统计
      this.prisma.stockAlert.groupBy({
        by: ['alertType'],
        where: { status: { in: [AlertStatus.PENDING, AlertStatus.ACKNOWLEDGED] } },
        _count: true,
      }),

      // 最多告警的零件
      this.prisma.stockAlert.groupBy({
        by: ['partId'],
        where: { status: { in: [AlertStatus.PENDING, AlertStatus.ACKNOWLEDGED] } },
        _count: true,
        orderBy: {
          _count: {
            partId: 'desc',
          },
        },
        take: 10,
      }),
    ]);

    // 获取告警最多的零件详情
    const topPartIds = topAlertedParts.map((a) => a.partId);
    const topPartsDetails = await this.prisma.part.findMany({
      where: { id: { in: topPartIds } },
      select: {
        id: true,
        partNumber: true,
        partNameEn: true,
        partNameCn: true,
        currentStock: true,
        minStock: true,
      },
    });

    const topPartsWithDetails = topAlertedParts.map((a) => {
      const detail = topPartsDetails.find((d) => d.id === a.partId);
      return {
        ...a,
        part: detail,
      };
    });

    return {
      totalAlerts,
      pendingAlerts,
      acknowledgedAlerts,
      resolvedAlerts,
      alertsBySeverity,
      alertsByType,
      topAlertedParts: topPartsWithDetails,
    };
  }

  /**
   * 自动解决已修复的告警
   */
  async autoResolveFixedAlerts() {
    // 查找所有待处理和已确认的告警
    const alerts = await this.prisma.stockAlert.findMany({
      where: {
        status: { in: [AlertStatus.PENDING, AlertStatus.ACKNOWLEDGED] },
      },
      include: {
        part: true,
      },
    });

    let resolvedCount = 0;

    for (const alert of alerts) {
      const { part } = alert;
      let shouldResolve = false;

      switch (alert.alertType) {
        case 'OUT_OF_STOCK':
          shouldResolve = part.currentStock > 0;
          break;
        case 'LOW_STOCK':
          shouldResolve = part.currentStock > part.minStock;
          break;
        case 'APPROACHING_MIN':
          shouldResolve = part.currentStock > part.minStock * 1.2;
          break;
        case 'OVERSTOCK':
          shouldResolve = !part.maxStock || part.currentStock <= part.maxStock;
          break;
      }

      if (shouldResolve) {
        await this.prisma.stockAlert.update({
          where: { id: alert.id },
          data: {
            status: AlertStatus.RESOLVED,
            resolvedBy: 'System',
            resolvedAt: new Date(),
            resolution: 'Auto-resolved: Stock level returned to normal',
          },
        });
        resolvedCount++;
      }
    }

    return {
      resolved: resolvedCount,
      message: `Auto-resolved ${resolvedCount} alert(s)`,
    };
  }
}

