// core/types/interfaces/resolver.ts
// Shared types for GraphQL resolver interface
//
// NOTE: This file defines the contract between resolver implementations (like OCAPResolver)
// and consumers (like @ocap/gql). Return types are flexible because:
// 1. Resolvers transform data before returning (e.g., formatTx, formatTokenMap)
// 2. Info methods construct objects rather than fetching exact Proto types
// 3. List methods use resolver-specific paging (IPaging) instead of IndexDB paging (TPageInfo)

// ============ Import Proto types ============
import type {
  TRequestEstimateGas,
  TRequestGetAccountState,
  TRequestGetAccountTokens,
  TRequestGetEvidenceState,
  TRequestGetRollupBlock,
  TRequestGetState,
  TRequestGetTokenDistribution,
  TRequestGetTx,
  TRequestListAssetTransactions,
  TRequestListAssets,
  TRequestListDelegations,
  TRequestListFactories,
  TRequestListRollupBlocks,
  TRequestListRollupValidators,
  TRequestListRollups,
  TRequestListStakes,
  TRequestListTokenFactories,
  TRequestListTokenFlows,
  TRequestListTokens,
  TRequestListTopAccounts,
  TRequestListTransactions,
  TRequestSearch,
  TRequestVerifyAccountRisk,
} from '../lib/rpc_pb';

import type { TGasEstimate } from '../lib/type_pb';

import type {
  TIndexedTokenFlow,
  TSearchResult,
  TTokenDistribution,
  TTokenMeta,
  TVerifyAccountRiskResult,
} from '../lib/trace-type_pb';

// ============ Import interface types ============
import type { RequiredBy } from './base';
import type {
  IAccountState,
  IAssetFactoryState,
  IAssetState,
  IDelegateState,
  IEvidenceState,
  IForeignToken,
  IRollupBlock,
  IRollupState,
  IRollupValidator,
  IStakeState,
  ITokenFactoryState,
  ITokenState,
  TokenBalanceMap,
} from './state';

import type { TTransactionReceipt } from '../lib/type_pb';
import type { TPageInfo } from './indexdb';

// Note: We don't import IList*Result from indexdb because resolver uses its own paging format

// ============ Resolver Context ============

/**
 * Request context passed to resolver methods from HTTP request
 * Index signature allows compatibility with Record<string, unknown>
 */
export interface IResolverContext {
  featureSwitch: Record<string, unknown>;
  gasStakeHeaders: { token: string; pk: string };
  request: { userAgent: string | undefined; ip: string; id: string };
  [key: string]: unknown;
}

// ============ Extended Request Args (Proto types missing fields) ============

/**
 * getAccountState args - extends TRequestGetAccountState with expandContext
 */
export interface IGetAccountStateArgs extends Partial<TRequestGetAccountState> {
  address: string;
  expandContext?: boolean;
}

/**
 * getAccountTokens args - token is optional (Proto requires it)
 */
export type IGetAccountTokensArgs = RequiredBy<Partial<TRequestGetAccountTokens>, 'address'>;

// ============ Token Info (Resolver formatted) ============

/**
 * Token info with balance - extends TTokenMeta with additional fields
 * Used for formatted token data in resolver responses
 */
export interface ITokenInfo extends Partial<TTokenMeta> {
  address: string;
  foreignToken?: IForeignToken | null;
  /** Token value for inputs/outputs */
  value?: string;
}

// ============ Extended State Types (tokens field format differs) ============

/**
 * Extended account state for resolver - tokens as ITokenInfo[] instead of TokenBalanceMap
 */
export interface IResolverAccountState extends Omit<IAccountState, 'tokens'> {
  tokens?: ITokenInfo[] | TokenBalanceMap;
}

/**
 * Extended stake state for resolver - tokens/revokedTokens as ITokenInfo[]
 */
export interface IResolverStakeState extends Omit<IStakeState, 'tokens' | 'revokedTokens'> {
  tokens?: ITokenInfo[] | TokenBalanceMap;
  revokedTokens?: ITokenInfo[] | TokenBalanceMap;
}

/**
 * Extended rollup state for resolver - with tokenInfo and statistics
 */
export interface IResolverRollupState extends IRollupState {
  tokenInfo?: ITokenInfo;
  foreignToken?: IForeignToken | null;
  totalDepositAmount?: string;
  totalWithdrawAmount?: string;
}

/**
 * Extended factory state for resolver - tokens as ITokenInfo[]
 */
export interface IResolverFactoryState extends Omit<IAssetFactoryState, 'tokens'> {
  tokens?: ITokenInfo[] | TokenBalanceMap;
}

// ============ Resolver Response Types ============

/**
 * Token flows list result
 */
export interface ITokenFlowsResult {
  data: TIndexedTokenFlow[];
  paging?: TPageInfo;
}

/**
 * Search result wrapper
 */
export interface ISearchResult {
  results: TSearchResult[];
}

/**
 * Estimate gas result
 */
export interface IEstimateGasResult {
  estimate: TGasEstimate;
}

/**
 * Empty blocks result (placeholder)
 */
export interface IBlocksResult {
  blocks: never[];
}

// ============ Address Args Helper ============

/**
 * Simple address args - used by multiple state getters
 */
export type IAddressArgs = Pick<TRequestGetState, 'address'>;

// ============ Resolver Paging ============

/**
 * Resolver paging - simpler than TPageInfo, used by list methods
 */
export interface IResolverPaging {
  size?: number;
  cursor?: string | number;
  order?: { field: string; type: string };
  total?: number;
  next?: boolean;
}

// ============ Resolver Transaction ============

/**
 * Transaction inner JSON structure
 */
export interface IResolverTxItxJson {
  _type?: string;
  type_url?: string;
  data?: Record<string, unknown>;
  address?: string;
  factory?: string;
  rollup?: string;
  tokenFactory?: string;
  evidence?: { hash: string };
  sender?: { tokens: ITokenInfo[] };
  receiver?: { tokens: ITokenInfo[] };
  tokens?: ITokenInfo[];
  inputs?: Array<{ tokens: ITokenInfo[] }>;
  outputs?: Array<{ tokens: ITokenInfo[] }>;
  withdraw_tx_hash?: string;
  token?: Partial<ITokenState>;
  endpoint?: string;
  actualFee?: string;
  [key: string]: unknown;
}

/**
 * Transaction in resolver format - returned by getTx, listTransactions, etc.
 * Different from TIndexedTransaction: resolver adds formatted tokens, receipts, etc.
 */
export interface IResolverTransaction {
  hash: string;
  time: string;
  code?: string;
  sender?: string;
  receiver?: string;
  receipts?: TTransactionReceipt[];
  tokenSymbols?: ITokenInfo[];
  accounts?: string[];
  tx: {
    from: string;
    itx: { typeUrl: string };
    itxJson: IResolverTxItxJson;
    signatures?: Array<{ signer: string }>;
    [key: string]: unknown;
  };
  [key: string]: unknown;
}

// ============ Resolver List Results ============

/**
 * Base list result with resolver paging
 */
interface IResolverListResult {
  paging?: IResolverPaging;
}

/**
 * Transactions list result
 */
export interface IResolverListTransactionsResult extends IResolverListResult {
  transactions: IResolverTransaction[];
}

/**
 * Assets list result
 */
export interface IResolverListAssetsResult extends IResolverListResult {
  assets: IAssetState[];
  account?: IResolverAccountState;
}

/**
 * Accounts list result
 */
export interface IResolverListAccountsResult extends IResolverListResult {
  accounts: IResolverAccountState[];
}

/**
 * Tokens list result
 */
export interface IResolverListTokensResult extends IResolverListResult {
  tokens: ITokenState[];
}

/**
 * Factories list result
 */
export interface IResolverListFactoriesResult extends IResolverListResult {
  factories: IResolverFactoryState[];
}

/**
 * Stakes list result
 */
export interface IResolverListStakesResult extends IResolverListResult {
  stakes: IResolverStakeState[];
}

/**
 * Delegations list result
 */
export interface IResolverListDelegationsResult extends IResolverListResult {
  delegations: IDelegateState[];
}

/**
 * Rollups list result
 */
export interface IResolverListRollupsResult extends IResolverListResult {
  rollups: IResolverRollupState[];
}

/**
 * Rollup blocks list result
 */
export interface IResolverListRollupBlocksResult extends IResolverListResult {
  blocks: IRollupBlock[];
}

/**
 * Rollup validators list result
 */
export interface IResolverListRollupValidatorsResult extends IResolverListResult {
  validators: Array<IRollupValidator & { availableStake?: string }>;
}

/**
 * Token factories list result
 */
export interface IResolverListTokenFactoriesResult extends IResolverListResult {
  tokenFactories: ITokenFactoryState[];
}

// ============ Resolver Info Types ============

/**
 * Chain info returned by getChainInfo
 * Constructed by resolver, not fetched from Proto
 */
export interface IResolverChainInfo {
  id: string;
  totalTxs?: number;
  blockHash?: string;
  blockHeight?: number;
  blockTime?: string;
  version?: string;
  address?: string;
  appHash?: string;
  consensusVersion?: string;
  forgeAppsVersion?: string[];
  moniker?: string;
  network?: string;
  supportedTxs?: string[];
  synced?: boolean;
  votingPower?: string;
  [key: string]: unknown;
}

/**
 * Node info returned by getNodeInfo
 */
export interface IResolverNodeInfo {
  id: string;
  address?: string;
  appHash?: string;
  consensusVersion?: string;
  forgeAppsVersion?: string[];
  geoInfo?: {
    city?: string;
    country?: string;
    latitude?: number;
    longitude?: number;
  };
  ip?: string;
  moniker?: string;
  network?: string;
  p2pAddress?: string;
  supportedTxs?: string[];
  synced?: boolean;
  votingPower?: string;
  [key: string]: unknown;
}

/**
 * Net info returned by getNetInfo
 */
export interface IResolverNetInfo {
  listening: boolean;
  listeners: string[];
  nPeers: number;
  peers: unknown[];
  [key: string]: unknown;
}

/**
 * Validators info returned by getValidatorsInfo
 */
export interface IResolverValidatorsInfo {
  blockHeight: number;
  validators: Array<{
    address: string;
    name?: string;
    proposerPriority?: string;
    votingPower?: string;
  }>;
  [key: string]: unknown;
}

/**
 * Forge stats returned by getForgeStats
 * Note: Values can be string or number due to legacy data formats
 */
export interface IResolverForgeStats {
  numBlocks?: (string | number)[];
  numTxs?: (string | number)[];
  numStakes?: (string | number)[];
  numValidators?: (string | number)[];
  numAccounts?: (string | number)[];
  numAssets?: (string | number)[];
  tps?: (string | number)[];
  [key: string]: unknown;
}

// ============ Main IResolver Interface ============

/**
 * Complete resolver interface with typed methods
 * Used by @ocap/gql to accept resolver implementations like OCAPResolver
 */
export interface IResolver {
  // ============ Transaction ============
  sendTx(args: { tx: string; extra?: Record<string, unknown> }, ctx?: IResolverContext): Promise<string>;

  // ============ Single State Getters ============
  getTx(args: TRequestGetTx, ctx?: IResolverContext): Promise<IResolverTransaction | null>;
  getBlock(): null;
  getBlocks(): never[];
  getUnconfirmedTxs(): never[];

  getAccountState(args: IGetAccountStateArgs, ctx?: IResolverContext): Promise<IResolverAccountState | null>;
  getAssetState(args: IAddressArgs, ctx?: IResolverContext): Promise<IAssetState | null>;
  getFactoryState(args: IAddressArgs, ctx?: IResolverContext): Promise<IResolverFactoryState | null>;
  getTokenState(args: IAddressArgs, ctx?: IResolverContext): Promise<ITokenState | null>;
  getStakeState(args: IAddressArgs, ctx?: IResolverContext): Promise<IResolverStakeState | null>;
  getRollupState(args: IAddressArgs, ctx?: IResolverContext): Promise<IResolverRollupState | null>;
  getRollupBlock(args: Partial<TRequestGetRollupBlock>, ctx?: IResolverContext): Promise<IRollupBlock | null>;
  getDelegateState(args: IAddressArgs, ctx?: IResolverContext): Promise<IDelegateState | null>;
  getTokenFactoryState(args: IAddressArgs, ctx?: IResolverContext): Promise<ITokenFactoryState | null>;
  getEvidenceState(args: TRequestGetEvidenceState, ctx?: IResolverContext): Promise<IEvidenceState | null>;
  getForgeState(): Promise<Record<string, unknown>>;

  // ============ Info Getters ============
  getChainInfo(): Promise<IResolverChainInfo>;
  getNodeInfo(): Promise<IResolverNodeInfo>;
  getNetInfo(): Promise<IResolverNetInfo>;
  getValidatorsInfo(): Promise<IResolverValidatorsInfo>;
  getConfig(): string;
  getForgeStats(): Promise<IResolverForgeStats>;

  // ============ Token Helpers ============
  getAccountTokens(args: IGetAccountTokensArgs, ctx?: IResolverContext): Promise<ITokenInfo[]>;
  getTokenDistribution(args?: Partial<TRequestGetTokenDistribution>): Promise<TTokenDistribution | null>;

  // ============ List Methods ============
  listTransactions(
    args?: Partial<TRequestListTransactions>,
    ctx?: IResolverContext
  ): Promise<IResolverListTransactionsResult>;
  listAssets(args?: Partial<TRequestListAssets>, ctx?: IResolverContext): Promise<IResolverListAssetsResult>;
  listAssetTransactions(
    args?: Partial<TRequestListAssetTransactions>,
    ctx?: IResolverContext
  ): Promise<IResolverListTransactionsResult>;
  listFactories(args?: Partial<TRequestListFactories>, ctx?: IResolverContext): Promise<IResolverListFactoriesResult>;
  listTopAccounts(args?: Partial<TRequestListTopAccounts>): Promise<IResolverListAccountsResult>;
  listTokens(args?: Partial<TRequestListTokens>, ctx?: IResolverContext): Promise<IResolverListTokensResult>;
  listTokenFactories(
    args?: Partial<TRequestListTokenFactories>,
    ctx?: IResolverContext
  ): Promise<IResolverListTokenFactoriesResult>;
  listStakes(args?: Partial<TRequestListStakes>, ctx?: IResolverContext): Promise<IResolverListStakesResult>;
  listRollups(args?: Partial<TRequestListRollups>, ctx?: IResolverContext): Promise<IResolverListRollupsResult>;
  listRollupBlocks(
    args?: Partial<TRequestListRollupBlocks>,
    ctx?: IResolverContext
  ): Promise<IResolverListRollupBlocksResult>;
  listRollupValidators(
    args?: Partial<TRequestListRollupValidators>,
    ctx?: IResolverContext
  ): Promise<IResolverListRollupValidatorsResult>;
  listDelegations(
    args?: Partial<TRequestListDelegations>,
    ctx?: IResolverContext
  ): Promise<IResolverListDelegationsResult>;
  listBlocks(): IBlocksResult;

  // ============ Search & Utility ============
  search(args: Partial<TRequestSearch>): Promise<ISearchResult>;
  estimateGas(args?: Partial<TRequestEstimateGas>): IEstimateGasResult;
  listTokenFlows(args: Partial<TRequestListTokenFlows>, ctx?: IResolverContext): Promise<ITokenFlowsResult> | never[];
  verifyAccountRisk(
    args: Partial<TRequestVerifyAccountRisk>,
    ctx?: IResolverContext
  ): Promise<TVerifyAccountRiskResult | null> | null;

  // ============ Lifecycle ============
  /**
   * Graceful shutdown: drain the transaction queue and stop accepting new requests.
   */
  shutdown(): Promise<void>;
}
