export interface PositionDistributionData {
  id?: bigint;
  userId: bigint;
  provinceCode: string | null;
  cityCode: string | null;
  treeCount: number;
}

export interface PlantingPositionData {
  id?: bigint;
  userId: bigint;
  totalTreeCount: number;
  effectiveTreeCount: number;
  pendingTreeCount: number;
  firstMiningStartAt?: Date | null;
  distributions?: PositionDistributionData[];
}

export class PositionDistribution {
  private _id: bigint | null;
  private readonly _userId: bigint;
  private readonly _provinceCode: string | null;
  private readonly _cityCode: string | null;
  private _treeCount: number;

  constructor(
    userId: bigint,
    provinceCode: string | null,
    cityCode: string | null,
    treeCount: number = 0,
    id?: bigint,
  ) {
    this._id = id || null;
    this._userId = userId;
    this._provinceCode = provinceCode;
    this._cityCode = cityCode;
    this._treeCount = treeCount;
  }

  get id(): bigint | null {
    return this._id;
  }
  get userId(): bigint {
    return this._userId;
  }
  get provinceCode(): string | null {
    return this._provinceCode;
  }
  get cityCode(): string | null {
    return this._cityCode;
  }
  get treeCount(): number {
    return this._treeCount;
  }

  addTrees(count: number): void {
    if (count <= 0) {
      throw new Error('添加数量必须大于0');
    }
    this._treeCount += count;
  }

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

  matchesLocation(provinceCode: string | null, cityCode: string | null): boolean {
    return this._provinceCode === provinceCode && this._cityCode === cityCode;
  }
}

export class PlantingPosition {
  private _id: bigint | null;
  private readonly _userId: bigint;
  private _totalTreeCount: number;
  private _effectiveTreeCount: number;
  private _pendingTreeCount: number;
  private _firstMiningStartAt: Date | null;
  private _distributions: PositionDistribution[];

  private constructor(
    userId: bigint,
    totalTreeCount: number = 0,
    effectiveTreeCount: number = 0,
    pendingTreeCount: number = 0,
  ) {
    this._id = null;
    this._userId = userId;
    this._totalTreeCount = totalTreeCount;
    this._effectiveTreeCount = effectiveTreeCount;
    this._pendingTreeCount = pendingTreeCount;
    this._firstMiningStartAt = null;
    this._distributions = [];
  }

  // Getters
  get id(): bigint | null {
    return this._id;
  }
  get userId(): bigint {
    return this._userId;
  }
  get totalTreeCount(): number {
    return this._totalTreeCount;
  }
  get effectiveTreeCount(): number {
    return this._effectiveTreeCount;
  }
  get pendingTreeCount(): number {
    return this._pendingTreeCount;
  }
  get firstMiningStartAt(): Date | null {
    return this._firstMiningStartAt;
  }
  get distributions(): ReadonlyArray<PositionDistribution> {
    return this._distributions;
  }

  /**
   * 工厂方法：创建新持仓
   */
  static create(userId: bigint): PlantingPosition {
    return new PlantingPosition(userId);
  }

  /**
   * 添加认种
   * 支付完成后直接生效，不再等待底池注入
   */
  addPlanting(
    treeCount: number,
    provinceCode: string | null,
    cityCode: string | null,
  ): void {
    if (treeCount <= 0) {
      throw new Error('认种数量必须大于0');
    }

    // 更新总数和有效数（直接生效）
    this._totalTreeCount += treeCount;
    this._effectiveTreeCount += treeCount;

    // 设置首次挖矿开始时间
    if (!this._firstMiningStartAt) {
      this._firstMiningStartAt = new Date();
    }

    // 更新省市分布
    let distribution = this._distributions.find((d) =>
      d.matchesLocation(provinceCode, cityCode),
    );

    if (distribution) {
      distribution.addTrees(treeCount);
    } else {
      distribution = new PositionDistribution(
        this._userId,
        provinceCode,
        cityCode,
        treeCount,
      );
      this._distributions.push(distribution);
    }
  }

  /**
   * 激活挖矿（底池注入后）
   */
  activateMining(treeCount: number): void {
    if (treeCount > this._pendingTreeCount) {
      throw new Error('激活数量不能超过待生效数量');
    }

    this._pendingTreeCount -= treeCount;
    this._effectiveTreeCount += treeCount;

    if (!this._firstMiningStartAt) {
      this._firstMiningStartAt = new Date();
    }
  }

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

  /**
   * 从数据库重建
   */
  static reconstitute(data: PlantingPositionData): PlantingPosition {
    const position = new PlantingPosition(
      data.userId,
      data.totalTreeCount,
      data.effectiveTreeCount,
      data.pendingTreeCount,
    );

    if (data.id) {
      position._id = data.id;
    }
    position._firstMiningStartAt = data.firstMiningStartAt || null;

    if (data.distributions) {
      position._distributions = data.distributions.map(
        (d) =>
          new PositionDistribution(
            d.userId,
            d.provinceCode,
            d.cityCode,
            d.treeCount,
            d.id,
          ),
      );
    }

    return position;
  }

  /**
   * 转换为可持久化的数据对象
   */
  toPersistence(): PlantingPositionData {
    return {
      id: this._id || undefined,
      userId: this._userId,
      totalTreeCount: this._totalTreeCount,
      effectiveTreeCount: this._effectiveTreeCount,
      pendingTreeCount: this._pendingTreeCount,
      firstMiningStartAt: this._firstMiningStartAt,
      distributions: this._distributions.map((d) => ({
        id: d.id || undefined,
        userId: d.userId,
        provinceCode: d.provinceCode,
        cityCode: d.cityCode,
        treeCount: d.treeCount,
      })),
    };
  }
}
