/**
 * Crypto.com Exchange OTC 2.0 API Type Definitions
 * Based on: https://exchange-docs.crypto.com/exchange/v1/rest-ws/index_OTC2.html
 */

// ============================================================================
// API Request/Response Base Types
// ============================================================================

export interface CryptoComApiRequest {
  id: number;
  method: string;
  params?: Record<string, unknown>;
  api_key?: string;
  sig?: string;
  nonce: number;
}

export interface CryptoComApiResponse<T = unknown> {
  id: number;
  method: string;
  result?: T;
  code: number;
  message?: string;
  original?: string;
}

// ============================================================================
// OTC Instrument Types
// ============================================================================

export interface OtcInstrument {
  instrument_name: string;
  base_currency: string;
  quote_currency: string;
  type: 'SPOT';
  price_tick_size: string;
  quote_decimals: number;
  qty_tick_size: string;
  qty_decimals: number;
}

export interface GetOtcInstrumentsResult {
  instrument_list: OtcInstrument[];
}

// ============================================================================
// Quote Request Types
// ============================================================================

export type SettlementArrangement = 'IMMEDIATE' | 'T1';
export type QuoteRequestDuration = '5000' | '10000' | '30000' | '60000' | '300000' | '600000';
export type QuoteTtl = '4000' | '5000';
export type TradeSide = 'BUY' | 'SELL';

export interface QuoteRequestLeg {
  instrument_name: string;
  side: TradeSide;
  quantity?: string;
  notional?: string;
}

export interface RequestQuoteParams {
  cl_quote_req_id: string;
  firm_quote?: boolean;
  settlement_arrangement?: SettlementArrangement;
  duration?: QuoteRequestDuration;
  quote_ttl?: QuoteTtl;
  leg_list: QuoteRequestLeg[];
}

export type QuoteRequestStatus = 'NEW' | 'ACTIVE' | 'COMPLETED' | 'REJECTED';

export interface QuoteRequest {
  quote_req_id: string;
  cl_quote_req_id: string;
  firm_quote?: boolean;
  settlement_arrangement?: SettlementArrangement;
  status: QuoteRequestStatus;
  reason?: string;
  request_time_ns?: string;
  leg_list: QuoteRequestLegResult[];
}

export interface QuoteRequestLegResult {
  instrument_name: string;
  quantity?: string;
  notional?: string;
  side: TradeSide;
  type?: 'PRICE';
}

export interface QuoteRequestUpdate {
  quote_req_id: string;
  cl_quote_req_id: string;
  status?: QuoteRequestStatus;
  reason?: string;
}

// ============================================================================
// Quote Types
// ============================================================================

export type QuoteStatus = 'ACTIVE' | 'EXPIRED' | 'EXECUTED';

export interface QuoteLeg {
  instrument_name: string;
  side?: TradeSide;
  quantity?: string;
  notional?: string;
  bid?: string;
  ask?: string;
  type?: 'PRICE';
}

export interface Quote {
  quote_id: string;
  quote_req_id: string;
  cl_quote_req_id: string;
  lp_quote_id?: string;
  status: QuoteStatus;
  reason: string;
  response_time_ns?: string;
  expiry_time_ns?: string;
  expire_time_ns?: string; // Alternative field name in some responses
  leg_list: QuoteLeg[];
}

// ============================================================================
// Deal Types
// ============================================================================

export type DealType = 'QUOTE_REQUEST';
export type DealStatus = 'ACCEPTED' | 'CONFIRMED' | 'SETTLED' | 'REJECTED';

export interface DealLeg {
  instrument_name: string;
  price: string;
  quantity?: string;
  notional?: string;
  executed_quantity?: string;
  executed_notional?: string;
  side: TradeSide;
  type?: 'PRICE';
}

export interface RequestDealParams {
  deal_type: DealType;
  cl_deal_id: string;
  quote_id: string;
  quote_req_id: string;
  leg_list: DealLeg[];
}

export interface Deal {
  deal_id: string;
  cl_deal_id: string;
  quote_id?: string;
  quote_req_id: string;
  deal_type: DealType;
  deal_status: DealStatus;
  settlement_arrangement?: SettlementArrangement;
  reason: string;
  create_time_ns?: string;
  update_time_ns: string;
  settle_time_ns?: string;
  leg_list: DealLeg[];
}

export interface RequestDealResult {
  deal_id: string;
  cl_deal_id: string;
  quote_id: string;
  quote_req_id: string;
  deal_type: DealType;
  deal_status: DealStatus;
  reason: string;
  update_time_ns: string;
  leg_list: DealLeg[];
}

// ============================================================================
// Query API Types
// ============================================================================

export interface GetOpenQuoteRequestsParams {
  cl_quote_req_id?: string;
  quote_req_id?: string;
  start_time?: number;
  end_time?: number;
  limit?: number;
}

export interface GetOpenQuoteRequestsResult {
  count: number;
  quote_request_list: QuoteRequest[];
}

export interface GetOpenQuotesParams {
  quote_id?: string;
  lp_quote_id?: string;
  start_time?: number;
  end_time?: number;
  limit?: number;
}

export interface GetOpenQuotesResult {
  count: number;
  quote_list: Quote[];
}

export interface GetQuoteRequestHistoryParams {
  cl_quote_req_id?: string;
  quote_req_id?: string;
  start_time?: number;
  end_time?: number;
  limit?: number;
}

export interface GetQuoteRequestHistoryResult {
  count: number;
  quote_request_list: QuoteRequest[];
}

export interface GetQuoteHistoryParams {
  quote_id?: string;
  lp_quote_id?: string;
  start_time?: number;
  end_time?: number;
  limit?: number;
}

export interface GetQuoteHistoryResult {
  count: number;
  quote_list: Quote[];
}

export interface GetOpenDealsParams {
  deal_type: DealType;
  deal_id?: string;
  start_time?: number;
  end_time?: number;
}

export interface GetOpenDealsResult {
  deal_list: Deal[];
}

export interface GetDealHistoryParams {
  deal_type: DealType;
  deal_id?: string;
  start_time?: number;
  end_time?: number;
}

export interface GetDealHistoryResult {
  deal_list: Deal[];
}

// ============================================================================
// Settle Later Types
// ============================================================================

export interface SettleLaterLimit {
  account_id: string;
  configured_limit: string;
  used_limit: string;
}

export interface UnsettledAmounts {
  unsettled_ccys: Record<string, Record<string, string>>;
}

// ============================================================================
// WebSocket Subscription Types
// ============================================================================

export type SubscriptionChannel =
  | 'user.otc_qr.requests'
  | 'user.otc_qr.quotes'
  | 'user.otc.deals';

export interface SubscriptionRequest {
  id: number;
  method: 'subscribe' | 'unsubscribe';
  params: {
    channels: SubscriptionChannel[];
  };
  nonce: number;
}

export interface SubscriptionResponse {
  id: number;
  method: string;
  code: number;
  message?: string;
}

export interface SubscriptionMessage<T = unknown> {
  id: number;
  method: string;
  code: number;
  result?: {
    subscription: string;
    channel: string;
    data: T[];
  };
}

// ============================================================================
// Error Types
// ============================================================================

export interface CryptoComError {
  code: number;
  message: string;
  data?: string;
}

// Quote Request Reason Codes
export enum QuoteRequestReasonCode {
  INVALID_REQUEST = 40003,
  MISSING_OR_INVALID_ARGUMENT = 40004,
  OTC_IS_SUSPENDED = 110002,
  ACCOUNT_DOES_NOT_EXIST = 401,
  USER_NOT_FOUND = 420,
  EXCEEDS_MAX_OPEN_QUOTE_REQUESTS = 110045,
  EXTERNAL_ID_MISSING = 110019,
  MISSING_SETTLE_TYPE = 110031,
  INVALID_DEAL_CHANNEL = 110018,
  DUPLICATE_CL_QUOTE_REQ_ID = 110020,
  LIQUIDITY_PROVIDER_NOT_FOUND = 110004,
  MISSING_LEG_INFO = 110043,
  INVALID_OTC_INSTRUMENT = 110013,
  USER_NO_OTC_QR_ACCESS = 110025,
  INVALID_ORDERQTY = 213,
  EXCEEDS_QUANTITY_LIMIT = 110050,
  INVALID_NOTIONAL = 238,
  NOTIONAL_AND_QTY_BOTH_PROVIDED = 110023,
  PROVIDED_FIELDS_MISSING = 110024,
  MARGIN_NOT_SUPPORTED = 111002,
  INVALID_SETTLE_TYPE = 110017,
  INVALID_SIDE = 220,
}

// Deal Reason Codes
export enum DealReasonCode {
  INSTRUMENT_NOT_TRADABLE = 208,
  INVALID_NOTIONAL = 238,
  INVALID_PRICE = 308,
  ACCOUNT_DOES_NOT_EXIST = 401,
  USER_NOT_FOUND = 420,
  OTC_IS_SUSPENDED = 110002,
  INVALID_DEAL_ID = 110009,
  DUPLICATE_DEAL_ID = 110010,
  USER_NO_OTC_QR_ACCESS = 110025,
  QUOTE_NOT_FOUND = 110026,
  QUOTE_REQUEST_NOT_FOUND = 110028,
  QUOTE_EXPIRED = 110029,
  QUOTE_NOT_ACTIVE = 110030,
  DUPLICATE_OTC_SYMBOL = 110032,
  MISSING_OTC_SYMBOL = 110033,
  MISSING_SIDE = 110034,
  SIDE_MISMATCH = 110035,
  QTY_MISMATCH = 110036,
}

// WebSocket Termination Codes
export enum WebSocketTerminationCode {
  NORMAL_DISCONNECT = 1000,
  ABNORMAL_DISCONNECT = 1006,
  SERVER_RESTARTING = 1013,
}

// ============================================================================
// Event Types
// ============================================================================

export interface CryptoComOtcEvents {
  quoteRequestUpdate: QuoteRequestUpdate;
  newQuote: Quote;
  dealUpdate: Deal;
  connected: void;
  disconnected: number;
  reconnected: void;
  error: Error;
}

// ============================================================================
// Configuration Types
// ============================================================================

export interface CryptoComOtcConfig {
  apiKey: string;
  apiSecret: string;
  environment?: 'production' | 'uat';
  reconnectInterval?: number;
  heartbeatInterval?: number;
  requestTimeout?: number;
}

export interface CryptoComRestClientConfig {
  apiKey: string;
  apiSecret: string;
  baseUrl?: string;
  timeout?: number;
}

export interface CryptoComWebSocketClientConfig {
  apiKey: string;
  apiSecret: string;
  wsUrl?: string;
  reconnectInterval?: number;
  heartbeatInterval?: number;
}
