/**
 * ShardId - Value Object for shard identity
 *
 * A shard identifies a specific mailbox within a realm.
 * For browser tabs, shard is currently always "00" (single shard model).
 *
 * IMPORTANT: Shard is NOT the same as exec-token or tab-suffix.
 * - Exec-token: identifies a runtime instance (tab-123abc)
 * - Shard: identifies a mailbox partition (00, 01, etc.)
 *
 * In browser, we use a single shard model where shard="00".
 * Future multi-shard scenarios would require coordination.
 */

const SHARD_ID_PATTERN = /^[a-z0-9]{2,8}$/;

/**
 * Default shard for browser tabs (single shard model).
 */
export const DEFAULT_SHARD = '00';

export class ShardId {
  private readonly _value: string;

  private constructor(value: string) {
    this._value = value;
  }

  /**
   * Create a ShardId from a string.
   * Throws if the value is invalid.
   */
  static of(value: string): ShardId {
    if (typeof value !== 'string') {
      throw new Error('ShardId must be a string');
    }

    const normalized = value.trim();

    if (!SHARD_ID_PATTERN.test(normalized)) {
      throw new Error(
        `Invalid ShardId: "${value}". Must be 2-8 lowercase alphanumeric characters.`
      );
    }

    return new ShardId(normalized);
  }

  /**
   * Create the default shard (for browser single-shard model).
   */
  static default(): ShardId {
    return new ShardId(DEFAULT_SHARD);
  }

  /**
   * Create a ShardId, returning default if invalid.
   */
  static tryOf(value: string | undefined | null): ShardId {
    if (!value) return ShardId.default();
    try {
      return ShardId.of(value);
    } catch {
      return ShardId.default();
    }
  }

  /**
   * Get the raw string value.
   */
  get value(): string {
    return this._value;
  }

  /**
   * Check equality with another ShardId.
   */
  equals(other: ShardId | null | undefined): boolean {
    if (!other) return false;
    return this._value === other._value;
  }

  /**
   * Check if this is the default shard.
   */
  isDefault(): boolean {
    return this._value === DEFAULT_SHARD;
  }

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

  toJSON(): string {
    return this._value;
  }
}

export function isShardId(value: unknown): value is ShardId {
  return value instanceof ShardId;
}
