import { BatchStatus } from '../value-objects/batch-status.enum';

export interface PoolInjectionBatchData {
  id?: bigint;
  batchNo: string;
  startDate: Date;
  endDate: Date;
  orderCount: number;
  totalAmount: number;
  status: BatchStatus;
  scheduledInjectionTime?: Date | null;
  actualInjectionTime?: Date | null;
  injectionTxHash?: string | null;
}

export class PoolInjectionBatch {
  private _id: bigint | null;
  private readonly _batchNo: string;
  private readonly _startDate: Date;
  private readonly _endDate: Date;
  private _orderCount: number;
  private _totalAmount: number;
  private _status: BatchStatus;
  private _scheduledInjectionTime: Date | null;
  private _actualInjectionTime: Date | null;
  private _injectionTxHash: string | null;

  private constructor(
    batchNo: string,
    startDate: Date,
    endDate: Date,
    orderCount: number = 0,
    totalAmount: number = 0,
  ) {
    this._id = null;
    this._batchNo = batchNo;
    this._startDate = startDate;
    this._endDate = endDate;
    this._orderCount = orderCount;
    this._totalAmount = totalAmount;
    this._status = BatchStatus.PENDING;
    this._scheduledInjectionTime = null;
    this._actualInjectionTime = null;
    this._injectionTxHash = null;
  }

  // Getters
  get id(): bigint | null {
    return this._id;
  }
  get batchNo(): string {
    return this._batchNo;
  }
  get startDate(): Date {
    return this._startDate;
  }
  get endDate(): Date {
    return this._endDate;
  }
  get orderCount(): number {
    return this._orderCount;
  }
  get totalAmount(): number {
    return this._totalAmount;
  }
  get status(): BatchStatus {
    return this._status;
  }
  get scheduledInjectionTime(): Date | null {
    return this._scheduledInjectionTime;
  }
  get actualInjectionTime(): Date | null {
    return this._actualInjectionTime;
  }
  get injectionTxHash(): string | null {
    return this._injectionTxHash;
  }

  /**
   * 工厂方法：创建新批次
   * 批次时间窗口为5天
   */
  static create(startDate: Date): PoolInjectionBatch {
    const endDate = new Date(startDate);
    endDate.setDate(endDate.getDate() + 5);

    const batchNo = `BATCH${startDate.getFullYear()}${String(startDate.getMonth() + 1).padStart(2, '0')}${String(startDate.getDate()).padStart(2, '0')}`;

    return new PoolInjectionBatch(batchNo, startDate, endDate);
  }

  /**
   * 添加订单到批次
   */
  addOrder(poolAmount: number): void {
    if (this._status !== BatchStatus.PENDING) {
      throw new Error('只有待处理状态的批次才能添加订单');
    }

    this._orderCount += 1;
    this._totalAmount += poolAmount;
  }

  /**
   * 安排注入时间
   */
  schedule(injectionTime: Date): void {
    if (this._status !== BatchStatus.PENDING) {
      throw new Error('只有待处理状态的批次才能安排注入');
    }

    this._scheduledInjectionTime = injectionTime;
    this._status = BatchStatus.SCHEDULED;
  }

  /**
   * 开始注入
   */
  startInjection(): void {
    if (this._status !== BatchStatus.SCHEDULED) {
      throw new Error('只有已排期状态的批次才能开始注入');
    }

    this._status = BatchStatus.INJECTING;
  }

  /**
   * 完成注入
   */
  completeInjection(txHash: string): void {
    if (this._status !== BatchStatus.INJECTING) {
      throw new Error('只有注入中状态的批次才能完成注入');
    }

    this._actualInjectionTime = new Date();
    this._injectionTxHash = txHash;
    this._status = BatchStatus.INJECTED;
  }

  /**
   * 检查日期是否在批次时间窗口内
   */
  isDateInWindow(date: Date): boolean {
    return date >= this._startDate && date <= this._endDate;
  }

  /**
   * 设置ID
   */
  setId(id: bigint): void {
    this._id = id;
  }

  /**
   * 从数据库重建
   */
  static reconstitute(data: PoolInjectionBatchData): PoolInjectionBatch {
    const batch = new PoolInjectionBatch(
      data.batchNo,
      data.startDate,
      data.endDate,
      data.orderCount,
      data.totalAmount,
    );

    if (data.id) {
      batch._id = data.id;
    }
    batch._status = data.status;
    batch._scheduledInjectionTime = data.scheduledInjectionTime || null;
    batch._actualInjectionTime = data.actualInjectionTime || null;
    batch._injectionTxHash = data.injectionTxHash || null;

    return batch;
  }

  /**
   * 转换为可持久化的数据对象
   */
  toPersistence(): PoolInjectionBatchData {
    return {
      id: this._id || undefined,
      batchNo: this._batchNo,
      startDate: this._startDate,
      endDate: this._endDate,
      orderCount: this._orderCount,
      totalAmount: this._totalAmount,
      status: this._status,
      scheduledInjectionTime: this._scheduledInjectionTime,
      actualInjectionTime: this._actualInjectionTime,
      injectionTxHash: this._injectionTxHash,
    };
  }
}
