import type { CommandStatus } from './types.js';

export type CommandMetadataField = 'commandType' | 'aggregateType' | 'aggregateId';

export class CommandMetadataConflictError extends Error {
  readonly code = 'COMMAND_METADATA_CONFLICT';

  constructor(
    commandKey: string,
    readonly field: CommandMetadataField,
  ) {
    super(`command claim ${field} conflict for key ${commandKey}`);
    this.name = 'CommandMetadataConflictError';
  }
}

export class CommandPayloadHashConflictError extends Error {
  readonly code = 'PAYLOAD_HASH_CONFLICT';

  constructor(commandKey: string) {
    super(`command claim payload hash conflict for key ${commandKey}`);
    this.name = 'CommandPayloadHashConflictError';
  }
}

export class CommandTerminalTransitionError extends Error {
  readonly code = 'ALREADY_TERMINAL';

  constructor(
    readonly status: Exclude<CommandStatus, 'CLAIMED'>,
    readonly transition: 'complete' | 'fail',
  ) {
    super(`command already terminal in ${status}; cannot ${transition}`);
    this.name = 'CommandTerminalTransitionError';
  }
}

export class CommandClaimLostError extends Error {
  readonly code = 'COMMAND_CLAIM_LOST';

  constructor(
    commandId: string,
    readonly transition: 'renew' | 'complete' | 'fail',
  ) {
    super(`command claim lost for ${commandId}; cannot ${transition}`);
    this.name = 'CommandClaimLostError';
  }
}

export class CommandNotFoundError extends Error {
  readonly code = 'COMMAND_NOT_FOUND';

  constructor(commandId: string) {
    super(`command record not found for id ${commandId}`);
    this.name = 'CommandNotFoundError';
  }
}
