/**
 * 账户序列号值对象
 *
 * V1 格式 (1.0系统): D + 年(2位) + 月(2位) + 日(2位) + 5位序号 = 12字符
 * 示例: D2512110008 -> 2025年12月11日的第8个注册用户
 *
 * V2 格式 (2.0系统): D + 年(2位) + 月(2位) + 日(2位) + 8位序号 = 15字符
 * 示例: D25121100000008 -> 2025年12月11日的第8个注册用户
 */
export class AccountSequence {
  private static readonly V1_PATTERN = /^D\d{11}$/;  // 12 字符
  private static readonly V2_PATTERN = /^D\d{14}$/;  // 15 字符
  private static readonly V1_LENGTH = 12;
  private static readonly V2_LENGTH = 15;
  private static readonly V2_SEQ_LENGTH = 8;
  private static readonly V2_MAX_DAILY_SEQ = 99999999;

  constructor(public readonly value: string) {
    if (!this.isValid(value)) {
      throw new Error(
        `账户序列号格式无效: ${value}，应为 D + 年月日(6位) + 序号(5位或8位)`,
      );
    }
  }

  private isValid(value: string): boolean {
    return AccountSequence.V1_PATTERN.test(value) || AccountSequence.V2_PATTERN.test(value);
  }

  static create(value: string): AccountSequence {
    return new AccountSequence(value);
  }

  /**
   * 生成 V2 格式的账户序列号
   * @param date 日期
   * @param dailySequence 当日序号 (0-99999999)
   */
  static generateV2(date: Date, dailySequence: number): AccountSequence {
    if (dailySequence < 0 || dailySequence > AccountSequence.V2_MAX_DAILY_SEQ) {
      throw new Error(`当日序号超出范围: ${dailySequence}，应为 0-${AccountSequence.V2_MAX_DAILY_SEQ}`);
    }
    const year = String(date.getFullYear()).slice(-2);
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    const seq = String(dailySequence).padStart(AccountSequence.V2_SEQ_LENGTH, '0');
    return new AccountSequence(`D${year}${month}${day}${seq}`);
  }

  /**
   * 判断是否为 V1 格式（来自 1.0 系统）
   */
  get isV1(): boolean {
    return this.value.length === AccountSequence.V1_LENGTH;
  }

  /**
   * 判断是否为 V2 格式（来自 2.0 系统）
   */
  get isV2(): boolean {
    return this.value.length === AccountSequence.V2_LENGTH;
  }

  /**
   * 获取用户来源
   */
  get source(): 'V1' | 'V2' {
    return this.isV1 ? 'V1' : 'V2';
  }

  /**
   * 从序列号中提取日期字符串 (YYMMDD)
   */
  get dateString(): string {
    return this.value.slice(1, 7);
  }

  /**
   * 从序列号中提取当日序号
   */
  get dailySequence(): number {
    return parseInt(this.value.slice(7), 10);
  }

  /**
   * 获取注册日期
   */
  get registrationDate(): Date {
    const dateStr = this.dateString;
    const year = 2000 + parseInt(dateStr.slice(0, 2), 10);
    const month = parseInt(dateStr.slice(2, 4), 10) - 1;
    const day = parseInt(dateStr.slice(4, 6), 10);
    return new Date(year, month, day);
  }

  equals(other: AccountSequence): boolean {
    return this.value === other.value;
  }

  toString(): string {
    return this.value;
  }
}
