// ============================================================
// types.ts — 统一行情数据类型定义与 MarketDataFeed 接口
// ============================================================
// 所有交易所适配器共享的数据结构和接口契约。
// 适配器负责将交易所原生数据格式转换为以下标准化类型。
//
// 设计原则：
//   - 字段语义与 Binance/OKX/Bybit 通用概念对齐
//   - 时间戳统一使用 Unix 毫秒（number），便于排序和计算
//   - 价格/数量使用 number 类型（JavaScript 64-bit float），
//     对精度敏感场景（如 orderbook 快照）保留原始字符串
// ============================================================

import type { Observable } from "rxjs";

import type { KlineInterval, PairType } from "./kline";

// ============================================================
// 标准化行情数据结构
// ============================================================

/** 24 小时滚动 Ticker 统计 */
export interface Ticker {
    /** 交易所标识 */
    exchange: string;
    /** 交易对符号（大写，如 BTCUSDT） */
    symbol: string;
    /** 最新成交价 */
    lastPrice: number;
    /** 24h 开盘价 */
    openPrice: number;
    /** 24h 最高价 */
    highPrice: number;
    /** 24h 最低价 */
    lowPrice: number;
    /** 24h 成交量（base 币种） */
    volume: number;
    /** 24h 成交额（quote 币种） */
    quoteVolume: number;
    /** 24h 价格变化 */
    priceChange: number;
    /** 24h 价格变化百分比（0.05 = 5%） */
    priceChangePercent: number;
    /** 买一价 */
    bidPrice: number;
    /** 买一量 */
    bidQty: number;
    /** 卖一价 */
    askPrice: number;
    /** 卖一量 */
    askQty: number;
    /** 事件发生时间（Unix ms） */
    eventTime: number;
    /** 交易所收盘时间（Unix ms，用于判断 K 线是否闭合） */
    closeTime: number;
}

/** 逐笔成交 */
export interface Trade {
    /** 交易所标识 */
    exchange: string;
    /** 交易对符号 */
    symbol: string;
    /** 成交价 */
    price: number;
    /** 成交数量（base 币种） */
    amount: number;
    /** 成交额（quote 币种 = price × amount） */
    quoteAmount: number;
    /** 成交时间（Unix ms） */
    timestamp: number;
    /** 买方是否为挂单方（true = 主动卖出 / taker sell） */
    isBuyerMaker: boolean;
    /** 交易所成交 ID（可能为字符串，如 Binance tradeId 为 bigint） */
    tradeId: string;
}

/** 订单簿深度快照 */
export interface OrderBook {
    /** 交易所标识 */
    exchange: string;
    /** 交易对符号 */
    symbol: string;
    /** 买单列表 [[price, qty], ...]，按价格降序（买一在前） */
    bids: [number, number][];
    /** 卖单列表 [[price, qty], ...]，按价格升序（卖一在前） */
    asks: [number, number][];
    /** 上次更新 ID */
    lastUpdateId: number;
    /** 事件发生时间（Unix ms） */
    eventTime: number;
}

/** 标准化 K 线（OHLCV） */
export interface Kline {
    /** 交易所标识 */
    exchange: string;
    /** 交易对符号 */
    symbol: string;
    /** 交易对类型（spot / um / cm） */
    type: PairType;
    /** K 线周期 */
    interval: KlineInterval;
    /** 开盘时间（Unix ms） */
    openTime: number;
    /** 收盘时间（Unix ms） */
    closeTime: number;
    /** 开盘价 */
    open: string;
    /** 最高价 */
    high: string;
    /** 最低价 */
    low: string;
    /** 收盘价 */
    close: string;
    /** 成交量（base 币种） */
    volume: string;
    /** 成交额（quote 币种） */
    quoteVolume: string;
    /** 主动买入成交量（base 币种） */
    takerBuyBaseVol: string;
    /** 主动买入成交额（quote 币种） */
    takerBuyQuoteVol: string;
    /** 成交笔数 */
    tradeCount: string;
    /** 该 K 线是否已关闭（不再更新） */
    isClosed: boolean;
}

/** K 线增量更新（仅推送最新一根 OHLCV 变化） */
export interface KlineDelta {
    exchange: string;
    symbol: string;
    interval: KlineInterval;
    openTime: number;
    closeTime: number;
    open: number;
    high: number;
    low: number;
    close: number;
    volume: number;
    isClosed: boolean;
}

// ============================================================
// WebSocket 连接状态
// ============================================================

/** 连接状态枚举 */
export type ConnectionState =
    | "disconnected"
    | "connecting"
    | "connected"
    | "error";

// ============================================================
// REST 客户端配置
// ============================================================

/** REST 客户端通用配置（各交易所 SDK 共用） */
export interface RestClientConfig {
    /** REST API 请求冷却时间（毫秒），默认 200 */
    restRateLimitMs: number;
    /** 单次请求默认拉取条数 */
    defaultLimit: number;
}

/** 默认 REST 客户端配置 */
export const DEFAULT_REST_CONFIG: RestClientConfig = {
    restRateLimitMs: 200,
    defaultLimit: 500,
};

// ============================================================
// fetchKlines 参数对象
// ============================================================

/** fetchKlines 统一参数对象 */
export interface FetchKlinesParams {
    /** 交易所标识（如 "binance"） */
    exchange: string;
    /** 交易对符号（如 BTCUSDT） */
    symbol: string;
    /** 交易对类型（spot / um / cm） */
    type: PairType;
    /** 起始时间（Unix ms） */
    startTime: number;
    /** 单次拉取条数，默认取自 config.defaultLimit */
    limit?: number;
    /** 结束时间（Unix ms），可选 */
    endTime?: number;
}

// ============================================================
// 适配器配置（含 WebSocket 重连）
// ============================================================

/** 交易所适配器完整配置（REST + WebSocket） */
export interface AdapterConfig extends RestClientConfig {
    /** 指数退避重连基数（毫秒），默认 3000 */
    reconnectBaseDelayMs: number;
    /** 最大重连次数，默认 10 */
    maxReconnectAttempts: number;
}

/** 默认适配器配置 */
export const DEFAULT_ADAPTER_CONFIG: AdapterConfig = {
    ...DEFAULT_REST_CONFIG,
    reconnectBaseDelayMs: 3000,
    maxReconnectAttempts: 10,
};

// ============================================================
// MarketDataFeed 接口 —— 所有交易所适配器必须实现
// ============================================================

/**
 * 统一行情数据源接口。
 *
 * 每个交易所适配器实现此接口，向上层管道暴露标准化数据流。
 * 使用 RxJS Observable 作为统一推送机制，pipeline 层可自由
 * 组合、过滤、分流各交易所数据。
 */
export interface MarketDataFeed {
    /** 交易所标识（如 "binance"） */
    readonly exchange: string;

    /** 当前连接状态 */
    readonly connectionState: ConnectionState;

    /** 建立 WebSocket 连接 */
    connect(): Promise<void>;

    /** 断开连接 */
    disconnect(): Promise<void>;

    /**
     * 订阅 24h 滚动 Ticker 流。
     * 每笔成交触发推送（Binance: <symbol>@ticker）。
     */
    subscribeTicker(symbols: string[]): Observable<Ticker>;

    /**
     * 订阅逐笔成交流。
     * 实时推送每笔撮合成交（Binance: <symbol>@trade）。
     */
    subscribeTrade(symbols: string[]): Observable<Trade>;

    /**
     * 订阅订单簿深度。
     * depth 参数指定档位（如 5/10/20），默认 20。
     */
    subscribeOrderbook(symbol: string, depth?: number): Observable<OrderBook>;

    /**
     * REST 拉取历史 K 线（用于补齐缺失数据或回测）。
     *
     * @param params - fetchKlines 统一参数对象
     * @returns 标准化 K 线数组，按时间升序
     */
    fetchKlines(params: FetchKlinesParams): Promise<Kline[]>;

    /**
     * 获取交易所交易对信息（用于自动注册到 trading_pairs 表）。
     * 返回标准化后的交易对元数据。
     */
    fetchMarkets(): Promise<MarketInfo[]>;
}

/** 交易对元信息（从交易所 REST API 获取） */
export interface MarketInfo {
    symbol: string;
    baseAsset: string;
    quoteAsset: string;
    pricePrecision: number;
    quantityPrecision: number;
    minQty?: number;
    stepSize?: number;
    minNotional?: number;
}

// ============================================================
// 工具类型
// ============================================================

/** Binance WebSocket 原始 K 线数据（kline 事件中的 k 字段） */
export interface BinanceRawKline {
    t: number;   // K 线开始时间
    T: number;   // K 线结束时间
    s: string;   // 交易对
    i: string;   // 周期
    o: string;   // 开盘价
    h: string;   // 最高价
    l: string;   // 最低价
    c: string;   // 收盘价
    v: string;   // 成交量
    n: number;   // 成交笔数
    x: boolean;  // 是否已关闭
    q: string;   // 成交额
    V: string;   // 主动买入成交量
    Q: string;   // 主动买入成交额
}
