/**
 * UCAN Complete TypeScript Type Definitions
 * User-Controlled Authorization Network v1.0.0-rc.1
 * 
 * Comprehensive types for Tokens, Delegation, and Invocation specifications
 */

// =============================================================================
// PRIMITIVES
// =============================================================================

/**
 * Decentralized Identifier (DID) string
 * @see https://www.w3.org/TR/did-core/
 */
export type DID = `did:${string}:${string}`;

/**
 * IPLD Content Identifier in DAG-JSON format
 * CIDv1 with DAG-CBOR codec and SHA-256 multihash, base58btc encoded
 */
export interface CID {
  "/": string;
}

/**
 * Binary data in DAG-JSON format (base64 encoded)
 */
export interface Bytes {
  "/": {
    bytes: string;
  };
}

/**
 * Unix timestamp in seconds (53-bit integer for JS compatibility)
 * Range: -9007199254740991 to 9007199254740991
 */
export type Timestamp = number;

/**
 * Nullable timestamp - null indicates non-expiring
 */
export type NullableTimestamp = Timestamp | null;

/**
 * Varsig v1 header containing cryptographic algorithm metadata
 */
export type VarsigHeader = Bytes;

/**
 * Raw signature bytes
 */
export type Signature = Bytes;

// =============================================================================
// COMMANDS
// =============================================================================

/**
 * UCAN Command - slash-delimited path describing the action
 * Must be lowercase, start with '/', no trailing slash
 */
export type Command =
  | "/"
  | `/${string}`
  | `/crud/${CRUDAction}`
  | `/msg/${MessageAction}`
  | `/ucan/${UCANAction}`
  | `/wasm/${WasmAction}`;

export type CRUDAction = "create" | "read" | "update" | "delete" | "mutate";
export type MessageAction = "send" | "receive";
export type UCANAction = "revoke";
export type WasmAction = "run";

// =============================================================================
// POLICY LANGUAGE
// =============================================================================

/**
 * jq-inspired selector for navigating IPLD data
 * @example "." | ".foo" | ".bar[0]" | ".items[-1]" | ".optional?"
 */
export type Selector = string;

/**
 * Glob pattern for 'like' operator
 * Use * for wildcard, \* for literal asterisk
 */
export type GlobPattern = string;

// Policy Operators
export type EqualityOperator = "==" | "!=";
export type InequalityOperator = ">" | ">=" | "<" | "<=";
export type ConnectiveOperator = "and" | "or";
export type QuantifierOperator = "all" | "any";

// Policy Statements
export type EqualityStatement = [EqualityOperator, Selector, unknown];
export type InequalityStatement = [InequalityOperator, Selector, number];
export type LikeStatement = ["like", Selector, GlobPattern];
export type NotStatement = ["not", PolicyStatement];
export type AndStatement = ["and", PolicyStatement[]];
export type OrStatement = ["or", PolicyStatement[]];
export type AllStatement = ["all", Selector, PolicyStatement];
export type AnyStatement = ["any", Selector, PolicyStatement];

/**
 * Union of all policy statement types
 */
export type PolicyStatement =
  | EqualityStatement
  | InequalityStatement
  | LikeStatement
  | NotStatement
  | AndStatement
  | OrStatement
  | AllStatement
  | AnyStatement;

/**
 * UCAN Policy - array of statements forming implicit AND
 */
export type Policy = PolicyStatement[];

// =============================================================================
// METADATA & ARGUMENTS
// =============================================================================

/**
 * Arbitrary metadata map
 */
export type Metadata = Record<string, unknown>;

/**
 * Command arguments - shape defined by command type
 */
export type Arguments = Record<string, unknown>;

// =============================================================================
// CAPABILITY
// =============================================================================

/**
 * UCAN Capability - the semantically-relevant claim of a delegation
 */
export interface Capability {
  /** Subject DID or null for powerline delegation */
  sub: DID | null;
  /** Command being delegated */
  cmd: Command;
  /** Policy constraints on invocation arguments */
  pol: Policy;
}

// =============================================================================
// DELEGATION
// =============================================================================

/**
 * UCAN Delegation Payload (ucan/dlg@1.0.0-rc.1)
 */
export interface DelegationPayload {
  /** Issuer DID - the delegator */
  iss: DID;
  /** Audience DID - the delegate */
  aud: DID;
  /** Subject DID or null for powerline */
  sub: DID | null;
  /** Command being delegated */
  cmd: Command;
  /** Policy constraints */
  pol: Policy;
  /** Random nonce for unique CID */
  nonce: Bytes;
  /** Optional metadata */
  meta?: Metadata;
  /** Not-before timestamp (optional) */
  nbf?: Timestamp;
  /** Expiration timestamp or null */
  exp: NullableTimestamp;
}

/**
 * Delegation signature payload structure
 */
export interface DelegationSigPayload {
  /** Varsig header */
  h: VarsigHeader;
  /** Delegation payload with version tag */
  "ucan/dlg@1.0.0-rc.1": DelegationPayload;
}

/**
 * Complete UCAN Delegation envelope
 */
export type Delegation = [Signature, DelegationSigPayload];

// =============================================================================
// INVOCATION
// =============================================================================

/**
 * Proof chain - ordered CIDs of delegations from Subject to Invoker
 */
export type ProofChain = CID[];

/**
 * UCAN Invocation Payload (ucan/inv@1.0.0-rc.1)
 */
export interface InvocationPayload {
  /** Issuer DID - the invoker */
  iss: DID;
  /** Subject DID being invoked */
  sub: DID;
  /** Optional audience DID if executor differs from subject */
  aud?: DID;
  /** Command to execute */
  cmd: Command;
  /** Command arguments */
  args: Arguments;
  /** Proof chain of delegations */
  prf: ProofChain;
  /** Optional metadata */
  meta?: Metadata;
  /** Optional nonce for non-idempotent invocations */
  nonce?: Bytes;
  /** Expiration timestamp */
  exp: NullableTimestamp;
  /** Optional issuance timestamp */
  iat?: Timestamp;
  /** Optional CID of Receipt that enqueued this task */
  cause?: CID;
}

/**
 * Invocation signature payload structure
 */
export interface InvocationSigPayload {
  /** Varsig header */
  h: VarsigHeader;
  /** Invocation payload with version tag */
  "ucan/inv@1.0.0-rc.1": InvocationPayload;
}

/**
 * Complete UCAN Invocation envelope
 */
export type Invocation = [Signature, InvocationSigPayload];

// =============================================================================
// TASK
// =============================================================================

/**
 * UCAN Task - subset of Invocation fields uniquely determining work
 * Task ID is the CID of these fields
 */
export interface Task {
  /** Subject DID */
  sub: DID;
  /** Command to execute */
  cmd: Command;
  /** Command arguments */
  args: Arguments;
  /** Nonce for uniqueness */
  nonce: Bytes;
}

// =============================================================================
// RECEIPT
// =============================================================================

/**
 * Successful execution result
 */
export interface SuccessResult<T = unknown> {
  ok: T;
}

/**
 * Failed execution result
 */
export interface ErrorResult<E = unknown> {
  err: E;
}

/**
 * Execution outcome
 */
export type ExecutionResult<T = unknown, E = unknown> = SuccessResult<T> | ErrorResult<E>;

/**
 * UCAN Receipt Payload - execution result
 */
export interface ReceiptPayload<T = unknown, E = unknown> {
  /** Executor DID */
  iss: DID;
  /** CID of executed Invocation */
  ran: CID;
  /** Execution result */
  out: ExecutionResult<T, E>;
  /** Effects - CIDs of Tasks to enqueue */
  fx?: CID[];
  /** Optional metadata */
  meta?: Metadata;
  /** Issuance timestamp */
  iat?: Timestamp;
}

// =============================================================================
// REVOCATION
// =============================================================================

/**
 * Revocation arguments
 */
export interface RevocationArgs {
  /** CID of delegation to revoke */
  ucan: CID;
}

/**
 * UCAN Revocation Payload
 */
export interface RevocationPayload {
  /** Revoker DID - must be issuer in delegation chain */
  iss: DID;
  /** Subject of delegation being revoked */
  sub: DID;
  /** Revocation command */
  cmd: "/ucan/revoke";
  /** Revocation arguments */
  args: RevocationArgs;
  /** Proof chain */
  prf: ProofChain;
  /** Nonce */
  nonce: Bytes;
  /** Expiration */
  exp: NullableTimestamp;
}

// =============================================================================
// ENVELOPE
// =============================================================================

/**
 * Generic UCAN Envelope format
 */
export type UCANEnvelope<P extends object> = [
  Signature,
  {
    h: VarsigHeader;
  } & P
];

// =============================================================================
// CRYPTOGRAPHY
// =============================================================================

/**
 * Supported signature algorithms
 */
export type CryptoAlgorithm = "Ed25519" | "P-256" | "secp256k1";

/**
 * Supported hash algorithms
 */
export type HashAlgorithm = "sha2-256";

// =============================================================================
// VALIDATION
// =============================================================================

/**
 * Validation error codes
 */
export type ValidationErrorCode =
  | "EXPIRED"
  | "NOT_YET_VALID"
  | "INVALID_SIGNATURE"
  | "PRINCIPAL_MISALIGNMENT"
  | "POLICY_VIOLATION"
  | "REVOKED"
  | "INVALID_PROOF_CHAIN"
  | "UNKNOWN_COMMAND"
  | "MALFORMED_TOKEN";

/**
 * Validation error structure
 */
export interface ValidationError {
  code: ValidationErrorCode;
  message: string;
  details?: Record<string, unknown>;
}

/**
 * Successful validation result
 */
export interface ValidationSuccess {
  valid: true;
  capability: Capability;
}

/**
 * Failed validation result
 */
export interface ValidationFailure {
  valid: false;
  error: ValidationError;
}

/**
 * Validation result union
 */
export type ValidationResult = ValidationSuccess | ValidationFailure;

// =============================================================================
// ROLES
// =============================================================================

/**
 * UCAN Agent Roles
 */
export interface Roles {
  /** General class of entities interacting with UCAN */
  Agent: DID;
  /** Principal delegated to in current UCAN (aud field) */
  Audience: DID;
  /** Agent that performs invocation action */
  Executor: DID;
  /** Principal requesting execution */
  Invoker: DID;
  /** Principal of current UCAN (iss field) */
  Issuer: DID;
  /** Subject controlling external resource */
  Owner: DID;
  /** Agent identified by DID */
  Principal: DID;
  /** Issuer in proof chain that revokes */
  Revoker: DID;
  /** Principal whose authority is delegated */
  Subject: DID;
  /** Agent interpreting UCAN validity */
  Validator: DID;
}

// =============================================================================
// COMMON COMMANDS (for convenience)
// =============================================================================

/**
 * Standard CRUD command arguments
 */
export namespace CRUDCommands {
  export interface CreateArgs {
    uri: string;
    payload: unknown;
    headers?: Record<string, string>;
  }

  export interface ReadArgs {
    uri: string;
    query?: Record<string, string>;
  }

  export interface UpdateArgs {
    uri: string;
    payload: unknown;
    headers?: Record<string, string>;
  }

  export interface DeleteArgs {
    uri: string;
  }
}

/**
 * Standard messaging command arguments
 */
export namespace MessageCommands {
  export interface SendArgs {
    from: string;
    to: string[];
    subject?: string;
    body: string;
    cc?: string[];
    bcc?: string[];
  }

  export interface ReceiveArgs {
    mailbox: string;
    since?: Timestamp;
    limit?: number;
  }
}

/**
 * WebAssembly execution command arguments
 */
export namespace WasmCommands {
  export interface RunArgs {
    /** Wasm module as data URI or CID */
    mod: string | CID;
    /** Function to execute */
    fun: string;
    /** Function parameters */
    params: unknown[];
  }
}

// =============================================================================
// TYPE GUARDS
// =============================================================================

export function isDID(value: unknown): value is DID {
  return typeof value === "string" && value.startsWith("did:");
}

export function isCID(value: unknown): value is CID {
  return (
    typeof value === "object" &&
    value !== null &&
    "/" in value &&
    typeof (value as CID)["/"] === "string"
  );
}

export function isBytes(value: unknown): value is Bytes {
  return (
    typeof value === "object" &&
    value !== null &&
    "/" in value &&
    typeof (value as Bytes)["/"] === "object" &&
    "bytes" in (value as Bytes)["/"]
  );
}

export function isSuccessResult<T>(result: ExecutionResult<T>): result is SuccessResult<T> {
  return "ok" in result;
}

export function isErrorResult<E>(result: ExecutionResult<unknown, E>): result is ErrorResult<E> {
  return "err" in result;
}

export function isDelegation(token: Delegation | Invocation): token is Delegation {
  return "ucan/dlg@1.0.0-rc.1" in token[1];
}

export function isInvocation(token: Delegation | Invocation): token is Invocation {
  return "ucan/inv@1.0.0-rc.1" in token[1];
}

// =============================================================================
// UTILITY TYPES
// =============================================================================

/**
 * Extract the payload type from a UCAN envelope
 */
export type ExtractPayload<E extends UCANEnvelope<object>> =
  E extends UCANEnvelope<infer P> ? P : never;

/**
 * Create a typed invocation for a specific command
 */
export type TypedInvocation<C extends Command, A extends Arguments> = [
  Signature,
  {
    h: VarsigHeader;
    "ucan/inv@1.0.0-rc.1": Omit<InvocationPayload, "cmd" | "args"> & {
      cmd: C;
      args: A;
    };
  }
];

/**
 * Create a typed delegation for a specific command
 */
export type TypedDelegation<C extends Command> = [
  Signature,
  {
    h: VarsigHeader;
    "ucan/dlg@1.0.0-rc.1": Omit<DelegationPayload, "cmd"> & {
      cmd: C;
    };
  }
];
