// core/types/interfaces/state.ts
// State interfaces that extend Proto T*State types for local storage format

import type {
  TAccountState,
  TAssetFactoryState,
  TAssetState,
  TDelegateState,
  TEvidenceState,
  TRollupBlock,
  TRollupState,
  TStakeState,
  TTokenFactoryState,
  TTokenState,
} from '../lib/state_pb';
import type { TCreateAssetTx } from '../lib/tx_pb';
import type {
  TAssetFactoryHook,
  TIndexedFactoryInput,
  TNFTDisplay,
  TNFTEndpoint,
  TStateContext,
  TVariableInput,
} from '../lib/type_pb';

/** Storage format with ISO 8601 string timestamps */
export interface IStateContext extends Omit<TStateContext, 'genesisTime' | 'renaissanceTime'> {
  genesisTime: string;
  renaissanceTime: string;
}

export interface IStateContextInput {
  txHash?: string;
  txTime?: string;
}

export interface IState {
  address: string;
  context?: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by state type */
  data?: unknown;
}

export interface IStateWithOwner extends IState {
  owner: string;
  issuer: string;
}

export type StateChangeType = 'create' | 'update' | 'delete';

/** State kind for change events - named to avoid conflict with StateType enum from enum_pb */
export type StateKind =
  | 'account'
  | 'asset'
  | 'token'
  | 'token-factory'
  | 'asset-factory'
  | 'stake'
  | 'delegation'
  | 'rollup'
  | 'rollup-block'
  | 'evidence';

export interface IStateChangeEvent<T extends IState = IState> {
  type: StateChangeType;
  stateType: StateKind;
  address: string;
  before?: T;
  after?: T;
}

// ============ Extended State Interfaces ============

/** Token balance map: tokenAddress -> amount */
export type TokenBalanceMap = Record<string, string>;

/** tokens: Record instead of Array<TIndexedTokenInput>, nonce: number instead of string */
export interface IAccountState
  extends Omit<
    TAccountState,
    'tokens' | 'nonce' | 'context' | 'balance' | 'gasBalance' | 'type' | 'numTxs' | 'numAssets' | 'data'
  > {
  tokens: TokenBalanceMap;
  nonce: number;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by account type */
  data?: unknown;
}

/** consumedTime: string (ISO 8601), endpoint/display with proper types */
export interface IAssetState extends Omit<TAssetState, 'consumedTime' | 'endpoint' | 'display' | 'context' | 'data'> {
  consumedTime: string;
  /** NFT endpoint - simplified to string (endpoint.id) in storage, or full object */
  endpoint?: string | TNFTEndpoint | null;
  /** NFT display metadata */
  display?: TNFTDisplay | null;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - application-specific asset data */
  data?: unknown;
}

export interface IForeignToken {
  contractAddress: string;
  [key: string]: unknown;
}

export interface ITokenMetadata {
  type: 'json';
  value?: {
    communityUrl?: string | null;
    issuer: string;
  };
}

/** foreignToken/metadata simplified, optional fields with null support */
export interface ITokenState
  extends Omit<
    TTokenState,
    | 'foreignToken'
    | 'metadata'
    | 'context'
    | 'data'
    | 'icon'
    | 'maxTotalSupply'
    | 'issuer'
    | 'website'
    | 'tokenFactoryAddress'
    | 'spenders'
    | 'minters'
    | 'type'
  > {
  foreignToken?: IForeignToken | null;
  metadata?: ITokenMetadata | null;
  icon?: string | null;
  maxTotalSupply?: string | null;
  issuer?: string | null;
  website?: string | null;
  tokenFactoryAddress?: string | null;
  spenders?: string[] | null;
  minters?: string[] | null;
  type?: 'Token' | 'CreditToken' | 'BondingCurveToken' | null;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by token type */
  data?: unknown;
}

/** Extends TAssetFactoryHook with compiled field for contract hooks */
export interface IFactoryHook extends TAssetFactoryHook {
  /** Compiled contract calls when type is 'contract' - structure varies by call type */
  compiled?: unknown[];
}

/** Factory input - extends TIndexedFactoryInput, tokens simplified to address+value */
export interface IFactoryInput extends Omit<TIndexedFactoryInput, 'tokens' | 'variables'> {
  /** Additional token requirements (without decimal/unit/symbol metadata) */
  tokens?: Array<{ address: string; value: string }>;
  /** Variable definitions (description optional in storage) */
  variables?: Array<Omit<TVariableInput, 'value' | 'description'> & { description?: string }>;
}

/** tokens: Record, hooks: IFactoryHook[], lastSettlement: string (ISO 8601) */
export interface IAssetFactoryState
  extends Omit<
    TAssetFactoryState,
    | 'tokens'
    | 'hooks'
    | 'lastSettlement'
    | 'input'
    | 'output'
    | 'display'
    | 'context'
    | 'data'
    | 'balance'
    | 'settlement'
    | 'limit'
  > {
  tokens: TokenBalanceMap;
  hooks?: IFactoryHook[];
  lastSettlement: string;
  /** Factory input - tokens/assets required to mint */
  input?: IFactoryInput;
  /** Factory output template for minted assets */
  output?: TCreateAssetTx;
  /** Display metadata for the factory itself */
  display?: TNFTDisplay | null;
  /** Settlement mode: 'instant' settles immediately, 'periodic' batches settlements */
  settlement?: 'instant' | 'periodic';
  /** Max number of assets that can be minted, 0 means unlimited */
  limit?: number;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - application-specific data */
  data?: unknown;
}

/** tokens/revokedTokens: Record instead of Array */
export interface IStakeState extends Omit<TStakeState, 'tokens' | 'revokedTokens' | 'context' | 'data'> {
  tokens: TokenBalanceMap;
  revokedTokens: TokenBalanceMap;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by stake type */
  data?: unknown;
}

/** Token limit in delegation ops */
export interface IDelegationTokenLimit {
  address: string;
  toList?: string[];
  txCount?: number;
  txAllowance?: string;
  totalAllowance?: string;
  validUntil?: number;
  rate?: { interval: number; anchor?: number } | null;
  txSent?: number;
  lastTx?: number;
  spentAllowance?: string;
}

/** Asset limit in delegation ops */
export interface IDelegationAssetLimit {
  address?: string[];
  toList?: string[];
  txCount?: number;
  validUntil?: number;
  rate?: { interval: number; anchor?: number } | null;
  txSent?: number;
  lastTx?: number;
}

/** Operation limit in delegation */
export interface IDelegationOpLimit {
  tokens?: IDelegationTokenLimit[];
  assets?: IDelegationAssetLimit[];
}

/** Delegation ops: typeUrl -> operation with limits */
export type IDelegationOps = Record<string, { limit: IDelegationOpLimit }>;

/** ops: IDelegationOps instead of opsMap */
export interface IDelegateState extends Omit<TDelegateState, 'opsMap' | 'context' | 'data' | 'deny' | 'validUntil'> {
  ops?: IDelegationOps | null;
  deny?: string[];
  validUntil?: number;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by delegation type */
  data?: unknown;
}

export interface IRollupValidator {
  pk: string;
  address: string;
  endpoint: string;
}

/** validators: IRollupValidator[], optional fields with null support */
export interface IRollupState
  extends Omit<
    TRollupState,
    | 'seedValidators'
    | 'validators'
    | 'context'
    | 'data'
    | 'vaultAddress'
    | 'blockHash'
    | 'issuer'
    | 'tokenInfo'
    | 'totalDepositAmount'
    | 'totalWithdrawAmount'
    | 'foreignToken'
  > {
  seedValidators: IRollupValidator[];
  validators: IRollupValidator[];
  vaultAddress?: string | null;
  blockHash?: string | null;
  issuer?: string | null;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by rollup type */
  data?: unknown;
}

/** Signature data for rollup blocks */
export interface IBlockSignature {
  signer: string;
  pk?: string | Uint8Array;
  signature?: string | Uint8Array;
}

/** address: alias for hash (StateDB key), signatures: IBlockSignature[] */
export interface IRollupBlock
  extends Omit<
    TRollupBlock,
    'signatures' | 'context' | 'data' | 'previousHash' | 'mintedAmount' | 'burnedAmount' | 'rewardAmount'
  > {
  address: string;
  signatures: IBlockSignature[];
  previousHash?: string | null;
  mintedAmount?: string | null;
  burnedAmount?: string | null;
  rewardAmount?: string | null;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by block type */
  data?: unknown;
}

/** address: alias for hash (StateDB key) */
export interface IEvidenceState extends Omit<TEvidenceState, 'context' | 'data'> {
  address: string;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by evidence type */
  data?: unknown;
}

export interface ITokenFactoryCurve {
  type: 'linear' | 'constant' | 'quadratic';
  basePrice?: string;
  slope?: string;
  fixedPrice?: string;
  constant?: number;
}

/** Narrows status to known string literals; uses runtime curve/context/token shapes; data as opaque payload */
export interface ITokenFactoryState
  extends Omit<TTokenFactoryState, 'status' | 'curve' | 'context' | 'token' | 'reserveToken' | 'data'> {
  status: 'ACTIVE' | 'PAUSED';
  curve?: ITokenFactoryCurve | null;
  context: IStateContext;
  /** Protobuf google.protobuf.Any - structure varies by token factory type */
  data?: unknown;
}
