import { PrePlantingOrderStatus } from '../value-objects/pre-planting-order-status.enum';
import { PRE_PLANTING_PRICE_PER_PORTION } from '../value-objects/pre-planting-right-amounts';
import { DomainEvent } from '../../../domain/events/domain-event.interface';
import { PrePlantingPortionPurchasedEvent } from '../events/pre-planting-portion-purchased.event';

export interface PrePlantingOrderData {
  id?: bigint;
  orderNo: string;
  userId: bigint;
  accountSequence: string;
  portionCount: number;
  pricePerPortion: number;
  totalAmount: number;
  priceSupplement?: number; // 总部运营成本压力涨价（每份加价金额），归总部 (S0000000001)
  provinceCode: string;
  cityCode: string;
  status: PrePlantingOrderStatus;
  mergedToMergeId?: bigint | null;
  mergedAt?: Date | null;
  createdAt?: Date;
  paidAt?: Date | null;
}

export class PrePlantingOrder {
  private _id: bigint | null;
  private readonly _orderNo: string;
  private readonly _userId: bigint;
  private readonly _accountSequence: string;
  private readonly _portionCount: number;
  private readonly _pricePerPortion: number;
  private readonly _totalAmount: number;
  private readonly _priceSupplement: number; // 总部运营成本压力涨价（每份加价金额）
  private readonly _provinceCode: string;
  private readonly _cityCode: string;
  private _status: PrePlantingOrderStatus;
  private _mergedToMergeId: bigint | null;
  private _mergedAt: Date | null;
  private readonly _createdAt: Date;
  private _paidAt: Date | null;

  private _domainEvents: DomainEvent[] = [];

  private constructor(
    orderNo: string,
    userId: bigint,
    accountSequence: string,
    portionCount: number,
    provinceCode: string,
    cityCode: string,
    priceSupplement: number = 0,
    createdAt?: Date,
  ) {
    this._id = null;
    this._orderNo = orderNo;
    this._userId = userId;
    this._accountSequence = accountSequence;
    this._portionCount = portionCount;
    this._pricePerPortion = PRE_PLANTING_PRICE_PER_PORTION + priceSupplement;
    this._totalAmount = portionCount * (PRE_PLANTING_PRICE_PER_PORTION + priceSupplement);
    this._priceSupplement = priceSupplement;
    this._provinceCode = provinceCode;
    this._cityCode = cityCode;
    this._status = PrePlantingOrderStatus.CREATED;
    this._mergedToMergeId = null;
    this._mergedAt = null;
    this._createdAt = createdAt || new Date();
    this._paidAt = null;
  }

  /**
   * 创建新的预种订单
   */
  /**
   * @param priceSupplement 总部运营成本压力涨价（每份加价金额），默认 0 不影响现有逻辑
   */
  static create(
    orderNo: string,
    userId: bigint,
    accountSequence: string,
    portionCount: number,
    provinceCode: string,
    cityCode: string,
    priceSupplement: number = 0,
  ): PrePlantingOrder {
    if (portionCount < 1) {
      throw new Error('购买份数必须大于 0');
    }
    return new PrePlantingOrder(
      orderNo,
      userId,
      accountSequence,
      portionCount,
      provinceCode,
      cityCode,
      priceSupplement,
    );
  }

  /**
   * 从持久化数据重建
   */
  static reconstitute(data: PrePlantingOrderData): PrePlantingOrder {
    const order = new PrePlantingOrder(
      data.orderNo,
      data.userId,
      data.accountSequence,
      data.portionCount,
      data.provinceCode,
      data.cityCode,
      data.priceSupplement || 0,
      data.createdAt,
    );
    order._id = data.id || null;
    order._status = data.status;
    order._mergedToMergeId = data.mergedToMergeId || null;
    order._mergedAt = data.mergedAt || null;
    order._paidAt = data.paidAt || null;
    return order;
  }

  /**
   * 标记为已支付
   */
  markAsPaid(
    totalPortionsAfter: number,
    availablePortionsAfter: number,
  ): void {
    if (this._status !== PrePlantingOrderStatus.CREATED) {
      throw new Error(`订单 ${this._orderNo} 状态不允许支付: ${this._status}`);
    }
    this._status = PrePlantingOrderStatus.PAID;
    this._paidAt = new Date();

    this._domainEvents.push(
      new PrePlantingPortionPurchasedEvent(this._orderNo, {
        orderNo: this._orderNo,
        userId: this._userId.toString(),
        accountSequence: this._accountSequence,
        portionCount: this._portionCount,
        totalAmount: this._totalAmount,
        provinceCode: this._provinceCode,
        cityCode: this._cityCode,
        totalPortionsAfter,
        availablePortionsAfter,
      }),
    );
  }

  /**
   * 标记为已合并
   */
  markAsMerged(mergeId: bigint): void {
    if (this._status !== PrePlantingOrderStatus.PAID) {
      throw new Error(`订单 ${this._orderNo} 状态不允许合并: ${this._status}`);
    }
    this._status = PrePlantingOrderStatus.MERGED;
    this._mergedToMergeId = mergeId;
    this._mergedAt = new Date();
  }

  setId(id: bigint): void {
    this._id = id;
  }

  get id(): bigint | null { return this._id; }
  get orderNo(): string { return this._orderNo; }
  get userId(): bigint { return this._userId; }
  get accountSequence(): string { return this._accountSequence; }
  get portionCount(): number { return this._portionCount; }
  get pricePerPortion(): number { return this._pricePerPortion; }
  get totalAmount(): number { return this._totalAmount; }
  /** 总部运营成本压力涨价（每份加价金额），归总部 (S0000000001) */
  get priceSupplement(): number { return this._priceSupplement; }
  get provinceCode(): string { return this._provinceCode; }
  get cityCode(): string { return this._cityCode; }
  get status(): PrePlantingOrderStatus { return this._status; }
  get mergedToMergeId(): bigint | null { return this._mergedToMergeId; }
  get mergedAt(): Date | null { return this._mergedAt; }
  get createdAt(): Date { return this._createdAt; }
  get paidAt(): Date | null { return this._paidAt; }

  get domainEvents(): DomainEvent[] { return [...this._domainEvents]; }
  clearDomainEvents(): void { this._domainEvents = []; }

  toPersistence(): PrePlantingOrderData {
    return {
      id: this._id || undefined,
      orderNo: this._orderNo,
      userId: this._userId,
      accountSequence: this._accountSequence,
      portionCount: this._portionCount,
      pricePerPortion: this._pricePerPortion,
      totalAmount: this._totalAmount,
      priceSupplement: this._priceSupplement,
      provinceCode: this._provinceCode,
      cityCode: this._cityCode,
      status: this._status,
      mergedToMergeId: this._mergedToMergeId,
      mergedAt: this._mergedAt,
      createdAt: this._createdAt,
      paidAt: this._paidAt,
    };
  }
}
