#pragma once

#include <atomic>
#include <cstdint>

#include "xlt_privilege_api.h"

/**
 * @brief XLTPrivilege Demo
 * 本类演示了如何使用XLTPrivilege管理接口进行操作，包括API初始化、登录、订阅交易回报、
 * 查询资金持仓订单信息、资金划转（主柜/双中心）、划拨执行、导出下场文件、解绑用户网关等。
 * 用户可以参考本类中的方法，根据实际业务场景进行调整和扩展。
 */
class XLTPrivilegeDemo : public x1::XLTPrivilegeSpi {
public:
    XLTPrivilegeDemo();
    ~XLTPrivilegeDemo() override = default;

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

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

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

    uint64_t get_account_index(uint64_t trade_token);

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

    /**
     * @brief 【演示】登录请求
     * 本方法演示XLTPrivilege登录过程
     * XLTPrivilege登录响应为异步响应，本方法封装为同步过程，用户根据实际业务场景进行调整。
     * 流程如下：
     * 1、发起登录请求（管理接口登录不需要client_id）
     * 2、等待异步响应
     * 3、判断是否登录成功，若成功，保存会话ID session_id_
     * 后续接口调用都需要用到本次登录返回的session_id_
     * @return 登录是否成功
     */
    bool login();

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

    /**
     * @brief 【演示】查询资金信息
     * 本方法演示如何查询资金信息
     * 结果将从on_query_assets回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_assets(uint64_t account_index);

    /**
     * @brief 【演示】查询持仓信息
     * 本方法演示如何查询持仓信息
     * 结果将从on_query_positions回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_positions(uint64_t account_index);

    /**
     * @brief 【演示】条件查询订单
     * 本方法演示如何查询订单信息
     * 结果将从on_query_orders回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_orders(uint64_t account_index);

    /**
     * @brief 【演示】分页查询订单
     * 本方法演示如何分页查询订单信息
     * 结果将从on_query_orders_by_page回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_orders_by_page(uint64_t account_index);

    /**
     * @brief 【演示】查询成交信息
     * 本方法演示如何查询成交信息
     * 结果将从on_query_trades回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_trades(uint64_t account_index);

    /**
     * @brief 【演示】查询初始资产
     * 本方法演示如何查询初始资产信息
     * 结果将从on_query_init_assets回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_init_assets(uint64_t account_index);

    /**
     * @brief 【演示】查询初始持仓
     * 本方法演示如何查询初始持仓信息
     * 结果将从on_query_init_positions回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_init_positions(uint64_t account_index);

    /**
     * @brief 【演示】查询交易账号信息
     * 本方法演示如何查询交易账号信息
     * 结果将从on_query_trade_account_info回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求是否发送成功
     */
    bool query_trade_account_info(uint64_t account_index=0);

    /**
     * @brief 【演示】查询简要资产
     * 本方法演示如何查询简要资产信息
     * 结果将从on_query_brief_assets回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_brief_assets(uint64_t account_index);

    /**
     * @brief 【演示】查询简要持仓
     * 本方法演示如何查询简要持仓信息
     * 结果将从on_query_brief_positions回调中返回
     * @param account_index 账号索引，0表示查询当前登录账号
     * @return 查询请求发送是否成功
     */
    bool query_brief_positions(uint64_t account_index);

    /**
     * @brief 【演示】导出下场文件
     * 本方法演示如何请求导出下场文件
     * 结果将从on_dump_final_file回调中返回
     * @return 请求发送是否成功
     */
    bool dump_final_file();

    /**
     * @brief 【演示】解绑用户与交易网关的绑定关系
     * 本方法演示如何解绑指定账号与交易网关的绑定关系
     * 结果将从on_unbind_user_tgw回调中返回
     * @param account_index 账号索引
     * @return 请求发送是否成功
     */
    bool unbind_user_tgw(uint64_t account_index);

    /**
     * @brief 【演示】提交主柜资金划转请求
     * 本方法演示如何提交主柜资金划转请求
     * 请求结果将从on_counter_fund_transfer_request回调中返回
     * @param biz_no 业务流水号
     * @param account_index 账号索引
     * @param side 划转方向，IN-划入（从主柜划入到xlight），OUT-划出（从xlight划出到主柜）
     * @param amount 划转金额（放大10000倍）
     * @return 请求发送是否成功
     */
    bool submit_counter_fund_transfer_request(const char* biz_no, uint64_t account_index, x1::FundTransSide side, x1::amount_t amount);

    /**
     * @brief 【演示】提交主柜资金划转结果
     * 本方法演示如何提交主柜资金划转结果
     * 结果将从on_counter_fund_transfer_result回调中返回
     * @param source 划拨来源
     * @param biz_no 业务流水号
     * @param account_index 账号索引
     * @param side 划转方向
     * @param amount 划转金额（放大10000倍）
     * @param status 划转状态
     * @param error_msg 错误信息（划转失败时填写）
     * @return 请求发送是否成功
     */
    bool submit_counter_fund_transfer_result(x1::FundTransSource source, const char* biz_no, uint64_t account_index,
                                             x1::FundTransSide side, x1::amount_t amount, x1::FundTransStatus status, const char* error_msg);

    /**
     * @brief 【演示】提交双中心资金划转请求
     * 本方法演示如何提交双中心资金划转请求
     * 请求结果将从on_cluster_fund_transfer_request回调中返回
     * @param biz_no 业务流水号
     * @param account_index 账号索引
     * @param amount 划转金额（放大10000倍）
     * @return 请求发送是否成功
     */
    bool submit_cluster_fund_transfer_request(const char* biz_no, uint64_t account_index, x1::amount_t amount);

    /**
     * @brief 【演示】提交双中心资金划转结果
     * 本方法演示如何提交双中心资金划转结果
     * 结果将从on_cluster_fund_transfer_result回调中返回
     * @param source 划拨来源
     * @param biz_no 业务流水号
     * @param account_index 账号索引
     * @param amount 划转金额（放大10000倍）
     * @param status 划转状态
     * @param error_msg 错误信息（划转失败时填写）
     * @return 请求发送是否成功
     */
    bool submit_cluster_fund_transfer_result(x1::FundTransSource source, const char* biz_no, uint64_t account_index,
                                             x1::amount_t amount, x1::FundTransStatus status, const char* error_msg);

    /**
     * @brief 【演示】插入资金划转执行请求
     * 本方法演示如何插入资金划转执行请求
     * 执行结果将从on_fund_transfer_exec_result回调中返回
     * @param biz_no 业务流水号
     * @param account_index 账号索引
     * @param side 划转方向
     * @param amount 划转金额（放大10000倍）
     * @param check_flag 校验标记
     * @param exec_type 执行类型
     * @return 请求发送是否成功
     */
    bool insert_fund_transfer_exec(const char* biz_no, uint64_t account_index, x1::FundTransSide side,
                                   x1::amount_t amount, uint8_t check_flag, x1::FundTransExecType exec_type);

    // ============== 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_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_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_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_fund_transfer_exec_result(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_fund_transfer_exec_result_t* fund_transfer_exec_result) 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;

    // ============== XLTPrivilegeSpi 回调 ==============
    void on_token(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_internal_token_info_t* token) override;
    void on_quote_login_info(uint64_t session_id, const x1::xlt_msg_desc_t* msg_desc, const x1::xlt_internal_quote_login_info_t* quote_login_info) override;
    void on_dump_final_file(uint64_t session_id, uint64_t request_id, bool success, const x1::xlt_error_info_t* error_info) override;
    void on_unbind_user_tgw(uint64_t session_id, uint64_t request_id, uint64_t account_index, const x1::xlt_error_info_t* error_info) override;
    void on_query_brief_assets(uint64_t session_id, uint64_t request_id, const x1::XLTBriefAssetList* brief_assets, bool is_last, const x1::xlt_error_info_t* error_info) override;
    void on_query_brief_positions(uint64_t session_id, uint64_t request_id, const x1::XLTBriefPositionList* brief_positions, bool is_last, const x1::xlt_error_info_t* error_info) override;

private:
    x1::XLTPrivilege* 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};


    uint64_t trade_token_{0};
    std::atomic<bool> auth_success_{false};
    std::atomic<bool> auth_finished_{false};
};

