import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '@core/database/prisma/prisma.service';
import { LabelStatus } from '@prisma/client';
import {
  GenerateLabelDto,
  BulkGenerateLabelsDto,
  PrintLabelDto,
  BulkPrintLabelsDto,
} from '../dto/part.dto';

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

  /**
   * 生成标签
   */
  async generateLabel(
    generateDto: GenerateLabelDto,
    userId: string,
    userName: string,
  ) {
    const { partId, template = 'standard', size = '50x30', quantity = 1 } = generateDto;

    // 检查零件是否存在
    const part = await this.prisma.part.findUnique({
      where: { id: partId },
    });

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

    const labels = [];

    for (let i = 0; i < quantity; i++) {
      const labelCode = await this.generateUniqueLabelCode(part.partNumber);
      const qrCodeData = this.generateQRCodeData(part, labelCode);

      const label = await this.prisma.partLabel.create({
        data: {
          partId,
          labelCode,
          qrCodeData,
          template,
          size,
          status: LabelStatus.ACTIVE,
        },
        include: {
          part: true,
        },
      });

      labels.push(label);
    }

    return {
      labels,
      message: `${quantity} label(s) generated successfully`,
    };
  }

  /**
   * 批量生成标签
   */
  async bulkGenerateLabels(
    bulkDto: BulkGenerateLabelsDto,
    userId: string,
    userName: string,
  ) {
    const {
      partIds,
      template = 'standard',
      size = '50x30',
      quantityPerPart = 1,
    } = bulkDto;

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

    for (const partId of partIds) {
      try {
        const result = await this.generateLabel(
          { partId, template, size, quantity: quantityPerPart },
          userId,
          userName,
        );

        results.success++;
        results.labels.push(...result.labels);
      } catch (error) {
        results.failed++;
        results.errors.push({
          partId,
          error: error.message,
        });
      }
    }

    return results;
  }

  /**
   * 打印标签
   */
  async printLabel(
    printDto: PrintLabelDto,
    userId: string,
    userName: string,
  ) {
    const { labelId, printerName } = printDto;

    const label = await this.prisma.partLabel.findUnique({
      where: { id: labelId },
      include: {
        part: true,
      },
    });

    if (!label) {
      throw new NotFoundException(`Label with ID ${labelId} not found`);
    }

    // 更新打印记录
    const updatedLabel = await this.prisma.partLabel.update({
      where: { id: labelId },
      data: {
        printCount: { increment: 1 },
        lastPrintedAt: new Date(),
        printedBy: userName,
      },
      include: {
        part: true,
      },
    });

    // 生成打印数据
    const printData = this.generatePrintData(updatedLabel, printerName);

    return {
      label: updatedLabel,
      printData,
      message: 'Label sent to printer',
    };
  }

  /**
   * 批量打印标签
   */
  async bulkPrintLabels(
    bulkDto: BulkPrintLabelsDto,
    userId: string,
    userName: string,
  ) {
    const { labelIds, printerName } = bulkDto;

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

    for (const labelId of labelIds) {
      try {
        const result = await this.printLabel(
          { labelId, printerName },
          userId,
          userName,
        );

        results.success++;
        results.printData.push(result.printData);
      } catch (error) {
        results.failed++;
        results.errors.push({
          labelId,
          error: error.message,
        });
      }
    }

    return results;
  }

  /**
   * 获取标签详情
   */
  async findOne(id: string) {
    const label = await this.prisma.partLabel.findUnique({
      where: { id },
      include: {
        part: true,
      },
    });

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

    return label;
  }

  /**
   * 通过 Label Code 查询标签
   */
  async findByLabelCode(labelCode: string) {
    const label = await this.prisma.partLabel.findUnique({
      where: { labelCode },
      include: {
        part: true,
      },
    });

    if (!label) {
      throw new NotFoundException(`Label with code ${labelCode} not found`);
    }

    return label;
  }

  /**
   * 获取零件的所有标签
   */
  async findByPartId(partId: string) {
    return this.prisma.partLabel.findMany({
      where: { partId },
      orderBy: { createdAt: 'desc' },
      include: {
        part: {
          select: {
            id: true,
            partNumber: true,
            partNameEn: true,
            partNameCn: true,
            station: true,
            warehouseLocation: true,
          },
        },
      },
    });
  }

  /**
   * 作废标签
   */
  async voidLabel(id: string, userId: string) {
    const label = await this.prisma.partLabel.findUnique({
      where: { id },
    });

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

    await this.prisma.partLabel.update({
      where: { id },
      data: {
        status: LabelStatus.VOID,
      },
    });

    return { message: 'Label voided successfully' };
  }

  /**
   * 生成唯一的标签代码
   */
  private async generateUniqueLabelCode(partNumber: string): Promise<string> {
    const timestamp = Date.now().toString(36).toUpperCase();
    const random = Math.random().toString(36).substring(2, 6).toUpperCase();
    return `LBL-${partNumber}-${timestamp}-${random}`;
  }

  /**
   * 生成二维码数据
   * 包含：Part Number、English Name、创建时间
   * 格式：JSON 字符串，便于扫码解析
   */
  private generateQRCodeData(part: any, labelCode: string): string {
    const data = {
      pn: part.partNumber,           // Part Number (简写以减少二维码大小)
      name: part.partNameEn,         // English Name
      ts: new Date().toISOString(),  // 创建时间 (timestamp)
    };
    return JSON.stringify(data);
  }

  /**
   * 生成打印数据
   * 支持 Zebra / Brother 打印机格式
   */
  private generatePrintData(label: any, printerName?: string) {
    const { part, labelCode, size } = label;

    // 判断打印机类型
    const isZebra = !printerName || printerName.toLowerCase().includes('zebra');
    const isBrother = printerName?.toLowerCase().includes('brother');

    if (isZebra) {
      // Zebra ZPL 格
      return this.generateZebraPrintData(label);
    } else if (isBrother) {
      // Brother ESC/P 格式
      return this.generateBrotherPrintData(label);
    } else {
      // 通用格式（JSON）
      return this.generateGenericPrintData(label);
    }
  }

  /**
   * 生成 Zebra 打印机 ZPL 格式
   * 简化版本：仅显示零件号和二维码
   */
  private generateZebraPrintData(label: any) {
    const { part, labelCode, qrCodeData, size } = label;

    // ZPL 标签模板（简化版）
    const zpl = `
^XA
^FO50,30^A0N,50,50^FD${part.partNumber}^FS
^FO50,100^BQN,2,6^FD${qrCodeData}^FS
^XZ
    `.trim();

    return {
      format: 'ZPL',
      printerType: 'Zebra',
      data: zpl,
      size,
    };
  }

  /**
   * 生成 Brother 打印机格式
   * 简化版本：仅显示零件号和二维码
   */
  private generateBrotherPrintData(label: any) {
    const { part, labelCode, qrCodeData, size } = label;

    return {
      format: 'BROTHER_PTOUCH',
      printerType: 'Brother',
      fields: [
        { type: 'text', content: part.partNumber, fontSize: 14 },
        { type: 'qrcode', content: qrCodeData, size: 100 },
      ],
      size,
    };
  }

  /**
   * 生成通用打印数据
   */
  private generateGenericPrintData(label: any) {
    const { part, labelCode, qrCodeData, size } = label;

    return {
      format: 'GENERIC',
      printerType: 'Generic',
      label: {
        partNumber: part.partNumber,
        partName: part.partName,
        partNameCn: part.partNameCn,
        station: part.station,
        warehouseLocation: part.warehouseLocation,
        labelCode,
        qrCodeData,
        qrCodeUrl: `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrCodeData)}`,
      },
      size,
    };
  }

  /**
   * 获取打印统计
   */
  async getPrintStats(startDate?: Date, endDate?: Date) {
    const where: any = {
      lastPrintedAt: { not: null },
    };

    if (startDate || endDate) {
      where.lastPrintedAt = {};
      if (startDate) {
        where.lastPrintedAt.gte = startDate;
      }
      if (endDate) {
        where.lastPrintedAt.lte = endDate;
      }
    }

    const [totalLabels, totalPrints, labelsByStatus] = await Promise.all([
      this.prisma.partLabel.count(),
      this.prisma.partLabel.aggregate({
        _sum: {
          printCount: true,
        },
        where,
      }),
      this.prisma.partLabel.groupBy({
        by: ['status'],
        _count: true,
      }),
    ]);

    return {
      totalLabels,
      totalPrints: totalPrints._sum.printCount || 0,
      labelsByStatus,
    };
  }
}

