import { GenericCrudService } from '@d8d/shared-crud';
import { DataSource, Repository } from 'typeorm';
import { FeiePrintTaskMt } from '../entities/feie-print-task.mt.entity';
import { FeiePrinterMt } from '../entities/feie-printer.mt.entity';
import { FeieApiService } from './feie-api.service';
import { PrinterService } from './printer.service';
import { FeieApiConfig, CreatePrintTaskDto, PrintStatus, PrintType, CancelReason } from '../types/feie.types';

export class PrintTaskService extends GenericCrudService<FeiePrintTaskMt> {
  private feieApiService: FeieApiService;
  private printerService: PrinterService;
  private printerRepository: Repository<FeiePrinterMt>;

  constructor(dataSource: DataSource, feieConfig: FeieApiConfig) {
    super(dataSource, FeiePrintTaskMt, {
      tenantOptions: { enabled: true, tenantIdField: 'tenantId' }
    });

    this.feieApiService = new FeieApiService(feieConfig);
    this.printerService = new PrinterService(dataSource, feieConfig);
    this.printerRepository = dataSource.getRepository(FeiePrinterMt);
  }

  /**
   * 创建打印任务
   */
  async createPrintTask(tenantId: number, taskDto: CreatePrintTaskDto): Promise<FeiePrintTaskMt> {
    // 验证打印机是否存在且可用
    const printer = await this.printerRepository.findOne({
      where: {
        tenantId,
        printerSn: taskDto.printerSn
      }
    });

    if (!printer) {
      throw new Error('打印机不存在');
    }

    // 生成任务ID
    const taskId = this.generateTaskId();

    // 计算计划打印时间
    let scheduledAt: Date | null = null;
    let printStatus = PrintStatus.PENDING;

    if (taskDto.delaySeconds && taskDto.delaySeconds > 0) {
      scheduledAt = new Date(Date.now() + taskDto.delaySeconds * 1000);
      printStatus = PrintStatus.DELAYED;
    }

    // 创建打印任务记录
    const printTask = await this.create({
      tenantId,
      taskId,
      orderId: taskDto.orderId || null,
      printerSn: taskDto.printerSn,
      content: taskDto.content,
      printType: taskDto.printType,
      printStatus,
      scheduledAt,
      retryCount: 0,
      maxRetries: 3
    });

    // 如果是立即打印，则立即执行
    if (!taskDto.delaySeconds || taskDto.delaySeconds <= 0) {
      await this.executePrintTask(tenantId, taskId);
    }

    return printTask;
  }

  /**
   * 执行打印任务
   */
  async executePrintTask(tenantId: number, taskId: string): Promise<FeiePrintTaskMt> {
    const task = await this.findOne({
      where: { tenantId, taskId }
    });

    if (!task) {
      throw new Error('打印任务不存在');
    }

    // 检查任务状态
    if (task.printStatus === PrintStatus.CANCELLED) {
      throw new Error('打印任务已取消');
    }

    if (task.printStatus === PrintStatus.SUCCESS) {
      throw new Error('打印任务已完成');
    }

    // 更新状态为打印中
    await this.update(task.id, {
      printStatus: PrintStatus.PRINTING,
      errorMessage: null
    });

    try {
      // 调用飞鹅API打印
      const response = await this.feieApiService.printReceipt({
        sn: task.printerSn,
        content: task.content,
        times: 1
      });

      // 更新任务状态
      const updatedTask = await this.update(task.id, {
        printStatus: PrintStatus.SUCCESS,
        printedAt: new Date(),
        errorMessage: null
      });

      return updatedTask;
    } catch (error) {
      // 处理打印失败
      const errorMessage = error instanceof Error ? error.message : '打印失败';

      // 检查是否需要重试
      const shouldRetry = task.retryCount < task.maxRetries;

      const updateData: Partial<FeiePrintTaskMt> = {
        errorMessage,
        retryCount: task.retryCount + 1
      };

      if (shouldRetry) {
        updateData.printStatus = PrintStatus.PENDING;
      } else {
        updateData.printStatus = PrintStatus.FAILED;
      }

      const updatedTask = await this.update(task.id, updateData);

      if (shouldRetry) {
        // 安排重试（5秒后）
        setTimeout(() => {
          this.executePrintTask(tenantId, taskId).catch(console.error);
        }, 5000);
      }

      throw error;
    }
  }

  /**
   * 取消打印任务
   */
  async cancelPrintTask(
    tenantId: number,
    taskId: string,
    reason: CancelReason = CancelReason.MANUAL
  ): Promise<FeiePrintTaskMt> {
    const task = await this.findOne({
      where: { tenantId, taskId }
    });

    if (!task) {
      throw new Error('打印任务不存在');
    }

    // 检查任务状态是否可以取消
    if ([PrintStatus.SUCCESS, PrintStatus.CANCELLED].includes(task.printStatus as PrintStatus)) {
      throw new Error(`打印任务状态为${task.printStatus}，无法取消`);
    }

    // 更新任务状态
    return this.update(task.id, {
      printStatus: PrintStatus.CANCELLED,
      cancelledAt: new Date(),
      cancelReason: reason
    });
  }

  /**
   * 重试打印任务
   */
  async retryPrintTask(tenantId: number, taskId: string): Promise<FeiePrintTaskMt> {
    const task = await this.findOne({
      where: { tenantId, taskId }
    });

    if (!task) {
      throw new Error('打印任务不存在');
    }

    // 检查任务状态是否可以重试
    if (task.printStatus !== PrintStatus.FAILED) {
      throw new Error('只有失败的打印任务可以重试');
    }

    // 重置重试计数和错误信息
    const updatedTask = await this.update(task.id, {
      printStatus: PrintStatus.PENDING,
      errorMessage: null,
      retryCount: 0
    });

    // 立即执行重试
    await this.executePrintTask(tenantId, taskId);

    return updatedTask;
  }

  /**
   * 查询打印任务状态
   */
  async getPrintTaskStatus(tenantId: number, taskId: string): Promise<any> {
    const task = await this.findOne({
      where: { tenantId, taskId }
    });

    if (!task) {
      throw new Error('打印任务不存在');
    }

    // 如果任务已完成，返回本地状态
    if (task.printStatus === PrintStatus.SUCCESS || task.printStatus === PrintStatus.CANCELLED) {
      return {
        taskId: task.taskId,
        printStatus: task.printStatus,
        printedAt: task.printedAt,
        cancelledAt: task.cancelledAt,
        cancelReason: task.cancelReason,
        errorMessage: task.errorMessage
      };
    }

    // 查询飞鹅API获取最新状态
    try {
      const response = await this.feieApiService.queryOrderStatus(taskId);

      // 根据飞鹅API响应更新本地状态
      let newStatus = task.printStatus;
      if (response.data === '已打印') {
        newStatus = PrintStatus.SUCCESS;
      } else if (response.data === '打印失败') {
        newStatus = PrintStatus.FAILED;
      }

      if (newStatus !== task.printStatus) {
        const updateData: Partial<FeiePrintTaskMt> = {
          printStatus: newStatus
        };

        if (newStatus === PrintStatus.SUCCESS) {
          updateData.printedAt = new Date();
        }

        await this.update(task.id, updateData);
      }

      return {
        taskId: task.taskId,
        printStatus: newStatus,
        remoteStatus: response.data,
        printedAt: task.printedAt,
        errorMessage: task.errorMessage
      };
    } catch (error) {
      // API查询失败，返回本地状态
      return {
        taskId: task.taskId,
        printStatus: task.printStatus,
        printedAt: task.printedAt,
        errorMessage: task.errorMessage,
        apiError: error instanceof Error ? error.message : '查询API失败'
      };
    }
  }

  /**
   * 获取打印任务列表
   */
  async getPrintTasks(
    tenantId: number,
    filters: {
      orderId?: number;
      printerSn?: string;
      printType?: PrintType;
      printStatus?: PrintStatus;
      startDate?: Date;
      endDate?: Date;
    } = {},
    page: number = 1,
    limit: number = 20
  ): Promise<{ tasks: FeiePrintTaskMt[]; total: number }> {
    const where: any = { tenantId };

    if (filters.orderId) {
      where.orderId = filters.orderId;
    }

    if (filters.printerSn) {
      where.printerSn = filters.printerSn;
    }

    if (filters.printType) {
      where.printType = filters.printType;
    }

    if (filters.printStatus) {
      where.printStatus = filters.printStatus;
    }

    if (filters.startDate || filters.endDate) {
      where.createdAt = {};
      if (filters.startDate) {
        where.createdAt.$gte = filters.startDate;
      }
      if (filters.endDate) {
        where.createdAt.$lte = filters.endDate;
      }
    }

    const [tasks, total] = await this.repository.findAndCount({
      where,
      order: { createdAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit
    });

    return { tasks, total };
  }

  /**
   * 获取待处理的延迟打印任务
   */
  async getPendingDelayedTasks(tenantId: number): Promise<FeiePrintTaskMt[]> {
    return this.findMany({
      where: {
        tenantId,
        printStatus: PrintStatus.DELAYED,
        scheduledAt: { $lte: new Date() }
      },
      order: { scheduledAt: 'ASC' }
    });
  }

  /**
   * 处理退款事件，取消相关打印任务
   */
  async handleRefundEvent(tenantId: number, orderId: number): Promise<void> {
    const tasks = await this.findMany({
      where: {
        tenantId,
        orderId,
        printStatus: PrintStatus.DELAYED
      }
    });

    for (const task of tasks) {
      await this.cancelPrintTask(tenantId, task.taskId, CancelReason.REFUND);
    }
  }

  /**
   * 生成任务ID
   */
  private generateTaskId(): string {
    const timestamp = Date.now();
    const random = Math.floor(Math.random() * 10000);
    return `FEIE_${timestamp}_${random}`;
  }
}