import { PrePlantingContractStatus } from '../value-objects/pre-planting-contract-status.enum';
import { PRE_PLANTING_PORTIONS_PER_TREE } from '../value-objects/pre-planting-right-amounts';
import { DomainEvent } from '../../../domain/events/domain-event.interface';
import { PrePlantingMergedEvent } from '../events/pre-planting-merged.event';
import { PrePlantingContractSignedEvent } from '../events/pre-planting-contract-signed.event';

export interface PrePlantingMergeData {
  id?: bigint;
  mergeNo: string;
  userId: bigint;
  accountSequence: string;
  sourceOrderNos: string[];
  treeCount: number;
  provinceCode?: string | null;
  cityCode?: string | null;
  contractStatus: PrePlantingContractStatus;
  contractSignedAt?: Date | null;
  miningEnabledAt?: Date | null;
  mergedAt?: Date;
}

export class PrePlantingMerge {
  private _id: bigint | null;
  private readonly _mergeNo: string;
  private readonly _userId: bigint;
  private readonly _accountSequence: string;
  private readonly _sourceOrderNos: string[];
  private readonly _treeCount: number;
  private _provinceCode: string | null;
  private _cityCode: string | null;
  private _contractStatus: PrePlantingContractStatus;
  private _contractSignedAt: Date | null;
  private _miningEnabledAt: Date | null;
  private readonly _mergedAt: Date;

  private _domainEvents: DomainEvent[] = [];

  private constructor(
    mergeNo: string,
    userId: bigint,
    accountSequence: string,
    sourceOrderNos: string[],
    provinceCode: string | null,
    cityCode: string | null,
    mergedAt?: Date,
  ) {
    this._id = null;
    this._mergeNo = mergeNo;
    this._userId = userId;
    this._accountSequence = accountSequence;
    this._sourceOrderNos = sourceOrderNos;
    this._treeCount = 1;
    this._provinceCode = provinceCode;
    this._cityCode = cityCode;
    this._contractStatus = PrePlantingContractStatus.PENDING;
    this._contractSignedAt = null;
    this._miningEnabledAt = null;
    this._mergedAt = mergedAt || new Date();
  }

  /**
   * 创建合并记录
   */
  static create(
    mergeNo: string,
    userId: bigint,
    accountSequence: string,
    sourceOrderNos: string[],
    provinceCode: string,
    cityCode: string,
    totalTreesMergedAfter: number,
  ): PrePlantingMerge {
    if (sourceOrderNos.length === 0) {
      throw new Error('合并至少需要 1 笔源订单');
    }

    const merge = new PrePlantingMerge(
      mergeNo,
      userId,
      accountSequence,
      sourceOrderNos,
      provinceCode,
      cityCode,
    );

    merge._domainEvents.push(
      new PrePlantingMergedEvent(mergeNo, {
        mergeNo,
        userId: userId.toString(),
        accountSequence,
        sourceOrderNos,
        treeCount: 1,
        provinceCode,
        cityCode,
        totalTreesMergedAfter,
      }),
    );

    return merge;
  }

  /**
   * 从持久化数据重建
   */
  static reconstitute(data: PrePlantingMergeData): PrePlantingMerge {
    const merge = new PrePlantingMerge(
      data.mergeNo,
      data.userId,
      data.accountSequence,
      data.sourceOrderNos,
      data.provinceCode || null,
      data.cityCode || null,
      data.mergedAt,
    );
    merge._id = data.id || null;
    merge._contractStatus = data.contractStatus;
    merge._contractSignedAt = data.contractSignedAt || null;
    merge._miningEnabledAt = data.miningEnabledAt || null;
    return merge;
  }

  /**
   * 签署合同
   */
  signContract(): void {
    if (this._contractStatus !== PrePlantingContractStatus.PENDING) {
      throw new Error(`合并 ${this._mergeNo} 合同状态不允许签署: ${this._contractStatus}`);
    }
    this._contractStatus = PrePlantingContractStatus.SIGNED;
    this._contractSignedAt = new Date();
    this._miningEnabledAt = new Date();

    this._domainEvents.push(
      new PrePlantingContractSignedEvent(this._mergeNo, {
        mergeNo: this._mergeNo,
        userId: this._userId.toString(),
        accountSequence: this._accountSequence,
        provinceCode: this._provinceCode || '',
        cityCode: this._cityCode || '',
        treeCount: this._treeCount,
      }),
    );
  }

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

  get id(): bigint | null { return this._id; }
  get mergeNo(): string { return this._mergeNo; }
  get userId(): bigint { return this._userId; }
  get accountSequence(): string { return this._accountSequence; }
  get sourceOrderNos(): string[] { return [...this._sourceOrderNos]; }
  get treeCount(): number { return this._treeCount; }
  get provinceCode(): string | null { return this._provinceCode; }
  get cityCode(): string | null { return this._cityCode; }
  get contractStatus(): PrePlantingContractStatus { return this._contractStatus; }
  get contractSignedAt(): Date | null { return this._contractSignedAt; }
  get miningEnabledAt(): Date | null { return this._miningEnabledAt; }
  get mergedAt(): Date { return this._mergedAt; }

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

  toPersistence(): PrePlantingMergeData {
    return {
      id: this._id || undefined,
      mergeNo: this._mergeNo,
      userId: this._userId,
      accountSequence: this._accountSequence,
      sourceOrderNos: this._sourceOrderNos,
      treeCount: this._treeCount,
      provinceCode: this._provinceCode,
      cityCode: this._cityCode,
      contractStatus: this._contractStatus,
      contractSignedAt: this._contractSignedAt,
      miningEnabledAt: this._miningEnabledAt,
      mergedAt: this._mergedAt,
    };
  }
}
