#pragma once

#include <atomic>
#include <cstdint>

#include "xlt_trade_api.h"

/**
 * @brief XLTTradeApi Demo
 * 本类演示了如何使用XLTTradeApi进行交易相关的操作，包括API初始化、登录、订阅交易回报、查询资金持仓订单信息、插入订单、撤单、资金划转等。
 * 用户可以参考本类中的方法，根据实际业务场景进行调整和扩展。
 */
class XLTTradeDemo : public x1::XLTTradeSpi {
public:
    XLTTradeDemo();
    ~XLTTradeDemo() override = default;

    XLTTradeDemo(const XLTTradeDemo&) = delete;
    XLTTradeDemo& operator=(const XLTTradeDemo&) = delete;

    const char* api_version() const;
    uint32_t trading_day() const;

    /**
     * @brief 【演示】获取下一个请求ID
     * XLTApi中使用request_id用于用户在异步回调中定位对应的请求。
     * XLTApi所有接口使用到request_id时，不对request_id做任何验证及业务假设，在回调中原样返回给用户。
     * 此方法用于演示request_id，用户可根据实际业务场景，自定义request_id。
     * @return 下一个请求ID
     */
    uint64_t next_request_id();

    /**
     * @brief 【演示】XLTTradeApi初始化
     *
     * 本方法演示如何配置以及初始化API，步骤如下：
     * 1、配置API
     * 2、初始化：设置API配置，以及注册交易回调接口和行情回调接口
     * @return 初始化是否成功
     * @remark XLTTradeApi必须在使用之前进行初始化，并且只能初始化一次
     */
    bool initialize();

    /**
     * @brief 【演示】登录请求
     * 本方法演示XLTTradeApi登录过程
     * XLTTradeApi登录响应为异步响应，本方法封装为同步过程，用户根据实际业务场景进行调整。
     * 流程如下：
     * 1、发起登录请求
     * 2、等待异步响应
     * 3、判断是否登录成功，若成功，保存会话ID global_session_id
     * 后续接口调用都需要用到本次登录返回的global_session_id
     * @return 登录是否成功
     * @remark 登录时，用户可自定义client_id，在本次登录中的所有委托及回报都将打上此标记，用于用户进行委托隔离
     */
    bool login();

    /**
     * @brief 【演示】订阅交易回报
     * 订阅交易数据(需要在登录成功后调用)
     * @return 订阅发送是否成功
     * @remark 只用订阅了交易回报，才能收到订单状态更新和成交回报等信息
     */
    bool subscribe_trade_message();

    /**
     * @brief 【演示】查询资金信息
     * 本方法演示如何查询资金信息
     * 结果将从on_query_assets回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_assets(uint64_t account_index=0);

    /**
     * @brief 【演示】查询持仓信息
     * 本方法演示如何查询持仓信息
     * 结果将从on_query_positions回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_positions(uint64_t account_index=0);

    /**
     * @brief 【演示】查询订单信息
     * 本方法演示如何查询订单信息
     * 结果将从on_query_orders回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_orders(uint64_t account_index=0);

    /**
     * @brief 【演示】分页查询订单信息
     * 本方法演示如何分页查询订单信息
     * 结果将从on_query_orders_by_page回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_orders_by_page(uint64_t account_index=0);

    /**
     * @brief 【演示】查询成交信息
     * 本方法演示如何查询成交信息
     * 结果将从on_query_trades回调中返回
     * @return 查询请求发送是否成功
     */
    bool query_trades(uint64_t account_index=0);

    /**
     * @brief 【演示】插入订单
     * 本方法演示如何插入订单
     * 订单响应将从on_order_response、on_trade_report、on_order_error_response、on_order_end回调中返回
     * @return 插入订单请求是否发送成功，返回xid表示发送成功，返回0表示发送失败
     */
    uint64_t insert_order();

    /**
     * @brief 【演示】撤单
     * 本方法演示如何撤单
     * 撤单响应将从on_cancel_response、on_order_error_response回调中返回
     * @return 撤单请求是否发送成功，返回cancel_xid表示发送成功，返回0表示发送失败
     */
    uint64_t cancel_order(uint64_t xid);

    /**
     * @brief 【演示】资金划转
     * 本方法演示如何提交资金划转请求
     * 资金划转请求结果将从on_fund_transfer_result回调中返回
     * @param side 划转方向，0表示从主柜台划转到xlight，1表示从xlight划转到主柜台
     * @param amount 划转金额
     * @param trade_token
     * @return 是否发送成功
     */
    bool submit_counter_fund_transfer_request(x1::FundTransSide side, x1::amount_t amount, uint64_t trade_token=0);

    /**
     * 双中心划拨
     * @param amount 划拨金额
     * @param trade_token
     * @return 是否发送成功
     */
    bool submit_cluster_fund_transfer_request(x1::amount_t amount, uint64_t trade_token=0);

    /**
     * @brief 【演示】重推消息
     * @param start_sequence 起始序号（从start_sequence+1开始推）
     * @param end_sequence 结束序号
     * @param account_index
     * @return 请求是否发送成功
     */
    bool rebuild_trade_message(uint64_t start_sequence, uint64_t end_sequence, uint64_t account_index=0);

    /**
     * @brief 【演示】查询初始资产
     * @return 查询请求是否发送成功
     */
    bool query_init_assets(uint64_t account_index = 0);

    /**
     * @brief 【演示】查询初始持仓
     * @return 查询请求是否发送成功
     */
    bool query_init_positions(uint64_t account_index = 0);

    /**
     * @brief 【演示】查询交易账号信息
     * @return 查询请求是否发送成功
     */
    bool query_trade_account_info(uint64_t account_index=0);


    /**
     * @brief 【演示】获取初始资产信息（同步接口，登录成功后可调用）
     */
    void print_init_assets();

    /**
     * @brief 【演示】获取初始持仓信息（同步接口，登录成功后可调用）
     */
    void print_init_positions();

    /**
     * @brief 【演示】获取账户索引（同步接口，登录成功后可调用）
     */
    uint64_t get_account_index();

    /**
     * @brief 【演示】交易授权认证
     * @param account_name 交易账号
     * @param password 登录密码
     * @return 请求是否发送成功
     */
    uint64_t auth_trade(const char* account_name, const char* password);

    /**
     * @brief 【演示】解除交易授权认证
     * @param trade_token 交易令牌
     * @return 请求是否发送成功
     */
    bool deauth_trade(uint64_t trade_token);

    /**
     * @brief 【演示】重发订单请求
     * @param xid 需要重发的订单ID
     * @return 请求是否发送成功
     */
    bool resend_order_request(uint64_t xid);

    bool dump_api_performance();

    // ---------------- XLTTradeSpi 回调 ----------------
    void on_disconnect(uint64_t session_id) override;
    void on_login(uint64_t session_id, uint64_t request_id, const x1::xlt_error_info_t* error_info) override;
    void on_auth_trade(uint64_t session_id, uint64_t request_id, uint64_t trade_token,
        const x1::xlt_error_info_t* error_info) override;

    void on_subscribe_trade_message(uint64_t session_id, uint64_t request_id, uint64_t start_sequence,
                                    uint64_t latest_sequence, const x1::xlt_error_info_t* error_info) override;

    void on_rebuild_trade_message(uint64_t session_id, uint64_t request_id, uint64_t start_sequence,
                                  uint64_t end_sequence, const x1::xlt_error_info_t* error_info) override;

    void on_order_end(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_order_end_t* order_end) override;
    void on_order_response(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_order_response_t* order_response) override;
    void on_cancel_response(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_cancel_response_t* cancel_response) override;
    void on_trade_report(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_trade_report_t* trade_report) override;
    void on_order_error_response(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_order_error_response_t* order_error_response) override;

    void on_raw_report(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, uint8_t client_id, uint64_t xid,
                       char report_id[32], x1::ExchangeIndex exchange_index, uint16_t platform_type, uint16_t
                       gateway_index, uint32_t report_size, char* raw_report) override;

    void on_order_book_insert(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc,
                                const x1::xlt_order_book_insert_t* order_insert) override;
    void on_order_book_update(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc,
                                     const x1::xlt_order_book_update_t* order_update) override;
    void on_order_book_error(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc,
                               const x1::xlt_order_book_error_t* order_error) override;
    void on_asset(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_asset_info_t* asset_info) override;
    void on_position(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc,
        const x1::xlt_position_info_t* position_info) override;

    void on_counter_fund_transfer_request(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_counter_fund_transfer_request_t* fund_transfer_request) override;
    void on_counter_fund_transfer_result(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_counter_fund_transfer_result_t* fund_transfer_result) override;
    void on_cluster_fund_transfer_request(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_cluster_fund_transfer_request_t* cluster_fund_transfer_request) override;
    void on_cluster_fund_transfer_result(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_cluster_fund_transfer_result_t* cluster_fund_transfer_result) override;

    void on_query_positions(uint64_t session_id, uint64_t request_id, const x1::XLTPositionList* positions, bool is_last,
                            const x1::xlt_error_info_t* error_info) override;

    void on_query_assets(uint64_t session_id, uint64_t request_id, const x1::XLTAssetList* assets, bool is_last,
                         const x1::xlt_error_info_t* error_info) override;

    void on_query_orders(uint64_t session_id, uint64_t request_id, const x1::XLTOrderList* orders, bool is_last,
                         const x1::xlt_error_info_t* error_info) override;

    void on_query_orders_by_page(uint64_t session_id, uint64_t request_id, const x1::XLTOrderList* order_infos,
                                 uint64_t req_count, uint64_t rsp_count, const x1::xlt_page_query_reference_t* query_reference,
                                 bool is_last, const x1::xlt_error_info_t* error_info) override;

    void on_query_trades(uint64_t session_id, uint64_t request_id, const x1::XLTTradeReportList* trade_reports, bool is_last,
                         const x1::xlt_error_info_t* error_info) override;

    void on_query_init_assets(uint64_t session_id, uint64_t request_id, const x1::XLTInitAssetList* init_assets, bool is_last,
                              const x1::xlt_error_info_t* error_info) override;

    void on_query_init_positions(uint64_t session_id, uint64_t request_id, const x1::XLTInitPositionList* init_positions, bool is_last,
                                 const x1::xlt_error_info_t* error_info) override;
    void on_query_trade_account_info(uint64_t session_id, uint64_t request_id, const x1::XLTTradeAccountInfoList* trade_account_infos, bool is_last, const x1::xlt_error_info_t* error_info) override;

    void on_order_timeout(uint64_t session_id, uint64_t xid) override;

private:
    x1::XLTTradeApi* api_{nullptr};

    uint64_t session_id_{0};
    std::atomic<bool> login_success_{false};
    std::atomic<bool> login_finished_{false};
    std::atomic<uint64_t> request_id_{0};

    // 以下为PB或者代理委托场景需要
    uint64_t trade_token_{0};
    std::atomic<bool> auth_success_{false};
    std::atomic<bool> auth_finished_{false};
};

