// similar to VerifiableCredentialSubject... maybe rename this
export interface GenericVerifiableCredential {
  "@context"?: string;
  "@type"?: string;
  [key: string]: unknown;
}

export interface GenericCredWrapper<T extends GenericVerifiableCredential> {
  claim: T;
  claimType?: string;
  handleId: string;
  id: string;
  issuedAt: string;
  issuer: string;
  publicUrls?: Record<string, string>;
}

export interface ErrorResponse {
  error?: {
    message?: string;
  };
}

export interface InternalError {
  error: string;
  userMessage?: string;
}

export interface KeyMeta {
  did: string;
  publicKeyHex: string;
  derivationPath?: string;
  passkeyCredIdHex?: string; // The Webauthn credential ID in hex, if this is from a passkey
}

export interface KeyMetaMaybeWithPrivate extends KeyMeta {
  mnemonic?: string; // 12 or 24 words encoding the seed
  identity?: string; // Stringified IIdentifier object from Veramo
}

export interface KeyMetaWithPrivate extends KeyMeta {
  mnemonic: string; // 12 or 24 words encoding the seed
  identity: string; // Stringified IIdentifier object from Veramo
}

export interface QuantitativeValue extends GenericVerifiableCredential {
  "@type"?: "QuantitativeValue";
  "@context"?: string;
  amountOfThisGood: number;
  unitCode: string;
}

export interface AxiosErrorResponse {
  message?: string;
  response?: {
    data?: {
      error?: {
        message?: string;
      };
      [key: string]: unknown;
    };
    status?: number;
    statusText?: string;
    config?: unknown;
  };
  config?: {
    url?: string;
    [key: string]: unknown;
  };
  [key: string]: unknown;
}

export interface UserInfo {
  did: string;
  name: string;
  publicEncKey: string;
  registered: boolean;
  profileImageUrl?: string;
  nextPublicEncKeyHash?: string;
}

export interface CreateAndSubmitClaimResult {
  success: boolean;
  error?: string;
  handleId?: string;
}

export interface Agent {
  identifier?: string;
  did?: string;
}

export interface ClaimObject {
  "@type": string;
  "@context"?: string;
  [key: string]: unknown;
}

export interface VerifiableCredentialClaim {
  "@context"?: string;
  "@type"?: string;
  credentialSubject: ClaimObject;
  [key: string]: unknown;
}

/**
 * Database constraint error types for consistent error handling
 */
export interface DatabaseConstraintError extends Error {
  name: "ConstraintError";
  message: string;
  constraint?: string;
}

/**
 * Database storage error types for IndexedDB/SQLite operations
 */
export interface DatabaseStorageError extends Error {
  name: "StorageError";
  message: string;
  code?: string;
  constraint?: string;
}

/**
 * Legacy Dexie error types for migration compatibility
 */
export interface DexieError extends Error {
  name: string;
  message: string;
  inner?: unknown;
  stack?: string;
}

/**
 * Type guard for database constraint errors
 */
export function isDatabaseConstraintError(
  error: unknown,
): error is DatabaseConstraintError {
  return error instanceof Error && error.name === "ConstraintError";
}

/**
 * Type guard for database storage errors
 */
export function isDatabaseStorageError(
  error: unknown,
): error is DatabaseStorageError {
  return error instanceof Error && error.name === "StorageError";
}

/**
 * Type guard for legacy Dexie errors
 */
export function isDexieError(error: unknown): error is DexieError {
  return (
    error instanceof Error &&
    (error.name === "DexieError" ||
      error.message.includes("Key already exists in the object store") ||
      error.message.includes("ConstraintError"))
  );
}

/**
 * Unified error type for database operations
 */
export type DatabaseError =
  | DatabaseConstraintError
  | DatabaseStorageError
  | DexieError;

/**
 * Type guard for any database error
 */
export function isDatabaseError(error: unknown): error is DatabaseError {
  return (
    isDatabaseConstraintError(error) ||
    isDatabaseStorageError(error) ||
    isDexieError(error)
  );
}
