use crate::coex::assets_managing_team;
use crate::coex::order_team;
use crate::coex::order_team::{BuyOrderedCoinList, SellOrderedCoinList};
use crate::coin_health_check_team::request_others::ExchangeInfo;
use crate::coin_health_check_team::*;
use crate::database_control::*;
use crate::time_checking_team::{UserTime, *};
use crate::RunningMode::*;
use crate::RUNNING_MODE;
use futures::future::try_join_all;
use reqwest::{Client, ClientBuilder};
use rust_decimal::{prelude::FromPrimitive, prelude::ToPrimitive, Decimal, RoundingStrategy};
use rust_decimal_macros::dec;
use sqlx::FromRow;
use std::{io, io::Write, path::Path, process::Stdio};
use tokio::{fs::*, io::ErrorKind, process::Command, task::JoinHandle, time::*};
use crate::future::order::*;
use crate::future::FuturesExchangeInfo;
use std::collections::HashMap;

const STRATEGIST_NUMBER: u32 = 16;

pub async fn initialization() {
    println!("- - - initialization start - - -");
    // initialize_webdriver().await;
    initialize_database().await;
    future_setup().await;
    println!("- - - initialization done - - -");
}

async fn initialize_webdriver() {
    print!("Open webdriver...");
    io::stdout().flush();
    let mut output;

    let os_type = std::env::consts::OS;
    let mut chrome_webdriver_path = std::path::PathBuf::new();
    chrome_webdriver_path.push(std::env::current_dir().unwrap());
    chrome_webdriver_path.push("chromedriver");

    match os_type {
        "linux" => {
            chrome_webdriver_path.push("chromedriver");
        }
        "windows" => {
            chrome_webdriver_path.push("chromedriver.exe");
        }
        _ => {
            eprintln!("\ntradingbot supports only Linux and Windows.");
            panic!();
        }
    }

    if !chrome_webdriver_path.exists() {
        eprintln!(
            "\nCheck if there is chromedriver.exe ({})",
            chrome_webdriver_path.to_str().unwrap()
        );
        panic!();
    }

    output = Command::new(chrome_webdriver_path)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn();
    output.expect("\nOpening chromedriver failed!");

    println!("Ok");
}

async fn future_setup() {
    print!(">>> Check future setting...");
    io::stdout().flush();
    let client = ClientBuilder::new()
        .timeout(tokio::time::Duration::from_millis(700))
        .build()
        .unwrap();

    let mut task_vec = Vec::new();
    let mut future_exchange_info_map: HashMap<String, FuturesExchangeInfo> = HashMap::new();
    request_future_exchange_infomation(&client, &mut future_exchange_info_map).await;
    for (symbol, futures_exchange_info) in future_exchange_info_map {
        let symbol_c = symbol.clone();
        let client_c = client.clone();
        task_vec.push(tokio::spawn(async move {
            set_margin_type(&symbol_c, MarginType::Isolated, &client_c).await;   // Default: Isolated
            set_initial_leverage(&symbol_c, 1, &client_c).await; // Default: x1
        }));
    }
    try_join_all(task_vec).await;
    
    set_position_mode(&client).await;   // Default: One-way Mode
    set_asset_mode(&client).await;  // Default: Single-Asset Mode
    println!("Ok");
}

async fn initialize_database() {
    let client = ClientBuilder::new()
        .timeout(tokio::time::Duration::from_millis(700))
        .build()
        .unwrap();

    println!(">>> Check database...");
    {
        print!("table 'time'...");
        io::stdout().flush();

        let table_name = String::from("time");
        let exists_table = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("server_epoch", "bigint", Some("UN")),
            ("local_epoch", "bigint", Some("UN")),
            ("epoch_difference", "bigint", None),
            ("server_ymdhs", "tinytext", None),
            ("local_ymdhs", "tinytext", None),
            ("last_server_epoch", "bigint", Some("UN")),
            ("last_server_ymdhs", "tinytext", None),
        ];
        let table_condition = None;
        let initial_columns = vec![
            "id",
            "server_epoch",
            "local_epoch",
            "epoch_difference",
            "server_ymdhs",
            "local_ymdhs",
            "last_server_epoch",
            "last_server_ymdhs",
        ];
        let initial_value = vec![
            String::from("1"),
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("----"),
            String::from("----"),
            String::from("0"),
            String::from("----"),
        ];

        if exists_table == false {
            new_table(&table_name, &initial_table, &table_condition)
                .await
                .expect("Failed to create table!");
        }

        delete_all_rows((&table_name)).await;
        insert_one_record(&table_name, &initial_columns, &initial_value).await;

        let mut usertime = UserTime::new();
        execute_time_check(&mut usertime, &client).await;
        println!("Ok");
    }

    {
        print!("table 'serverhealth'...");
        io::stdout().flush();

        let table_name = String::from("serverhealth");
        let exists_table = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("server_on", "tinyint", None),
            ("ping_on", "tinyint", None),
            ("wallet_system_on", "tinyint", None),
            ("waiting_maximum", "integer", Some("UN")),
        ];
        let table_condition = None;
        let initial_columns = vec![
            "id",
            "server_on",
            "ping_on",
            "wallet_system_on",
            "waiting_maximum",
        ];
        let initial_value = vec![
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("0"),
        ];

        if exists_table == false {
            new_table(&table_name, &initial_table, &table_condition)
                .await
                .expect("Failed to create table!");
        }

        delete_all_rows(&table_name).await;
        insert_one_record(&table_name, &initial_columns, &initial_value).await;

        println!("Ok");
    }

    {
        print!("table 'all_24h_change'...");
        io::stdout().flush();
        let client = ClientBuilder::new()
            .timeout(tokio::time::Duration::from_millis(1200))
            .build()
            .unwrap();
        let table_name = String::from("all_24h_change");
        let exists_table = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("symbol", "char(20)", None),
            ("priceChange", "double", None),
            ("priceChangePercent", "double", None),
            ("weightedAvgPrice", "double", None),
            ("prevClosePrice", "double", None),
            ("lastPrice", "double", None),
            ("lastQty", "double", None),
            ("bidPrice", "double", None),
            ("bidQty", "double", None),
            ("askPrice", "double", None),
            ("askQty", "double", None),
            ("openPrice", "double", None),
            ("highPrice", "double", None),
            ("lowPrice", "double", None),
            ("volume", "double", None),
            ("quoteVolume", "double", None),
            ("openTime", "bigint", None),
            ("closeTime", "bigint", None),
            ("firstId", "bigint", None),
            ("lastId", "bigint", None),
            ("count", "int", None),
        ];
        let table_condition = None;

        if exists_table == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition)
                .await
                .expect("Failed to create table!");
        }

        let mut result = request_others::request_24hr_ticker_price_change_statistics(&client).await;
        while let Err(E) = result {
            result = request_others::request_24hr_ticker_price_change_statistics(&client).await;
            sleep(Duration::from_millis(100));
        }
        println!("Ok");
    }

    {
        print!("table 'stop_usdt_trades'...");
        io::stdout().flush();

        let table_name = String::from("stop_usdt_trades");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("symbol", "char(20)", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }
        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");
        println!("Ok");
    }

    {
        print!("table 'banned_usdt_trades'...");
        io::stdout().flush();

        let table_name = String::from("banned_usdt_trades");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("symbol", "char(20)", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
            let columns = vec!["symbol"];
            // add fiat and unnessesary coins
            let value_wrapper = vec![
                vec![String::from("BUSDUSDT")],
                vec![String::from("USTCUSDT")],
                vec![String::from("FDUSDUSDT")],
                vec![String::from("TUSDUSDT")],
                vec![String::from("USDPUSDT")],
                vec![String::from("SUSDUSDT")],
                vec![String::from("AUDUSDT")],
                vec![String::from("EURUSDT")],
                vec![String::from("GBPUSDT")],
                vec![String::from("USDCUSDT")],
                vec![String::from("BZRXUSDT")],
                vec![String::from("USTUSDT")],
                vec![String::from("NBTUSDT")],
                vec![String::from("VGXUSDT")],
                vec![String::from("RAMPUSDT")],
                vec![String::from("TORNUSDT")],
                vec![String::from("BTTCUSDT")],
                vec![String::from("BTCSTUSDT")],
                vec![String::from("ACAUSDT")],
                vec![String::from("ANCUSDT")],
            ];
            insert_records(&table_name, &columns, &value_wrapper)
                .await
                .unwrap();
        }
        println!("Ok");
    }

    {
        print!("table 'valid_usdt_trades'...");
        io::stdout().flush();

        let table_name = String::from("valid_usdt_trades");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("symbol", "char(20)", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }
        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");

        monitors::initialize_valid_usde_trade().await;
        println!("Ok");
    }

    {
        print!("table 'indices'...");
        io::stdout().flush();

        let table_name = String::from("indices");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("server_epoch", "bigint", Some("UN")),
            ("total_24h_change_profit_index", "double", None),
            ("usdt_24h_change_profit_index", "double", None),
            ("total_price_down_dist_index", "double", None),
        ];
        let initial_columns = vec![
            "server_epoch",
            "total_24h_change_profit_index",
            "usdt_24h_change_profit_index",
            "total_price_down_dist_index",
        ];
        let initial_values = vec![
            String::from("0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");
        insert_one_record(&table_name, &initial_columns, &initial_values)
            .await
            .expect("Failed to insert initial record!");

        println!("Ok");
    }

    {
        print!("table 'market_cap_index'...");
        io::stdout().flush();

        let table_name = String::from("market_cap_index");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("market_cap_index", "double", None),
            ("minimum", "double", None),
            ("maximum", "double", None),
            ("transition_point", "double", None),
            ("liquidation_signal", "tinyint", None),
            ("negative_buy_signal", "tinyint", None),
            ("transition_buy_signal", "tinyint", None),
            ("comment", "char(11)", None),
        ];
        let initial_columns = vec![
            "market_cap_index",
            "minimum",
            "maximum",
            "transition_point",
            "liquidation_signal",
            "negative_buy_signal",
            "transition_buy_signal",
            "comment",
        ];
        let initial_values = vec![
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("5hrs angle"),
        ];
        let initial_values2 = vec![
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("5days angle"),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");
        insert_one_record(&table_name, &initial_columns, &initial_values)
            .await
            .expect("Failed to insert initial record!");
        insert_one_record(&table_name, &initial_columns, &initial_values2)
            .await
            .expect("Failed to insert initial record!");

        println!("Ok");
    }

    {
        use crate::signal_association::exchange_rate;
        print!("table 'foreign_exchange_rates'...");
        io::stdout().flush();

        let table_name = String::from("foreign_exchange_rates");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("date", "date", None),
            ("RUB", "double", None),
            ("CAD", "double", None),
            ("IQD", "double", None),
            ("CNY", "double", None),
            ("BRL", "double", None),
            ("IRR", "double", None),
            ("MXN", "double", None),
            ("NOK", "double", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        // delete_all_rows(&table_name).await.expect("Failed to delete rows!");

        // // initialize table
        // exchange_rate::initialize_record().await;
        println!("Ok");
    }

    {
        use crate::signal_association::dollar_index;
        print!("table 'dollar_index'...");
        io::stdout().flush();

        let table_name = String::from("dollar_index");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("date", "date", None),
            ("value", "char(10)", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");

        println!("Ok");
    }

    {
        print!("table 'signal_decision'...");
        io::stdout().flush();

        let table_name = String::from("signal_decision");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("decision", "char(11)", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        let initial_columns = vec!["decision"];
        let initial_values = vec![String::from("-")];

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");
        insert_one_record(&table_name, &initial_columns, &initial_values)
            .await
            .expect("Failed to insert initial record!");
        println!("Ok");
    }

    // {
    //     print!("table 'all_coin_start_price'...");
    //     io::stdout().flush();

    //     let table_name = String::from("all_coin_start_price");
    //     let exists_result = exists_table(&table_name).await;
    //     let initial_table = vec![("id", "integer", Some("PK, AI")),
    //                              ("symbol", "char(20)", None),
    //                              ("start_price", "double", None)];
    //     let table_condition = Some("ENGINE = MEMORY");;

    //     if exists_result == false {
    //         let mut result = new_table(&table_name, &initial_table, &table_condition).await;
    //         if result.is_err() {
    //             loop {
    //                 result = new_table(&table_name, &initial_table, &table_condition).await;
    //                 if result.is_ok(){ break; }
    //                 sleep(Duration::from_millis(10)).await;
    //             }
    //         }
    //     }

    //     delete_all_rows(&table_name).await.expect("Failed to delete rows!");

    //     // insert initial records
    //     crate::monitors::initial_all_coin_start_price().await;

    //     println!("Ok");
    // }

    // {
    //     print!("table 'all_coin_profit_change_avg'...");
    //     io::stdout().flush();

    //     let table_name = String::from("all_coin_profit_change_avg");
    //     let exists_result = exists_table(&table_name).await;
    //     let initial_table = vec![("id", "integer", Some("PK, AI")),
    //         ("server_epoch", "bigint", Some("UN")),
    //         ("cnt", "integer", Some("UN")),
    //         ("avg_profit", "double", None)];
    //     let initial_columns = vec![
    //         "server_epoch",
    //         "cnt",
    //         "avg_profit"];
    //     let initial_values = vec![
    //         String::from("0"),
    //         String::from("1"),
    //         String::from("0.0")];
    //     let table_condition = Some("ENGINE = MEMORY");;

    //     if exists_result == false {
    //         let mut result = new_table(&table_name, &initial_table, &table_condition).await;
    //         if result.is_err() {
    //             loop {
    //                 result = new_table(&table_name, &initial_table, &table_condition).await;
    //                 if result.is_ok(){ break; }
    //                 sleep(Duration::from_millis(10)).await;
    //             }
    //         }
    //     }

    //     delete_all_rows(&table_name).await.expect("Failed to delete rows!");
    //     insert_one_record(&table_name, &initial_columns, &initial_values).await.expect("Failed to insert initial record!");

    //     println!("Ok");
    // }

    // {
    //     print!("table 'all_coin_profit_change_history'...");
    //     io::stdout().flush();

    //     let table_name = String::from("all_coin_profit_change_history");
    //     let exists_result = exists_table(&table_name).await;
    //     let initial_table = vec![("id", "integer", Some("PK, AI")),
    //         ("server_epoch", "bigint", Some("UN")),
    //         ("avg_profit", "double", None)];
    //     let table_condition = Some("ENGINE = MEMORY");;

    //     if exists_result == false {
    //         let mut result = new_table(&table_name, &initial_table, &table_condition).await;
    //         if result.is_err() {
    //             loop {
    //                 result = new_table(&table_name, &initial_table, &table_condition).await;
    //                 if result.is_ok(){ break; }
    //                 sleep(Duration::from_millis(10)).await;
    //             }
    //         }
    //     }

    //     delete_all_rows(&table_name).await.expect("Failed to delete rows!");

    //     println!("Ok");
    // }

    {
        print!("table 'signal_association_opinion'...");
        io::stdout().flush();

        let table_name = String::from("signal_association_opinion");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("name", "char(30)", None),
            ("is_working", "tinyint", None),
            ("opinion", "char(5)", None),
            ("weight", "double", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");

        // insert initial records
        crate::signal_association::coinmarketcap::initialize_association_record().await;
        crate::signal_association::exchange_rate::initialize_association_record().await;
        crate::signal_association::dollar_index::initialize_association_record().await;
        crate::signal_association::future_ratio::initialize_association_record().await;

        println!("Ok");
    }

    // COEX DB part
    {
        // achievement_evaluation
        print!("table 'achievement_evaluation'...");
        io::stdout().flush();

        let table_name = String::from("achievement_evaluation");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("strategist", "smallint", Some("UN")),
            ("invested_usdt", "decimal(16,8)", Some("UN")),
            ("usdt_profit", "decimal(16,8)", None), // usdt_profit reflects tradefees(two takers)
            ("profit_percent", "double", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
        }

        let insert_initial_columns = vec![
            "strategist",
            "invested_usdt",
            "usdt_profit",
            "profit_percent",
        ];
        let mut insert_initial_value = vec![
            String::new(),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
        ];

        for number in (0..STRATEGIST_NUMBER) {
            insert_initial_value[0] = (number + 1).to_string();
            insert_one_record(&table_name, &insert_initial_columns, &insert_initial_value)
                .await
                .expect("Failed to insert initial row!");
        }

        println!("Ok");
    }

    {
        // suggested_coin_list
        print!("table 'suggested_coin_list'...");
        io::stdout().flush();

        let table_name = String::from("suggested_coin_list");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("symbol", "char(20)", None),
            ("suggested_price", "decimal(16,8)", None),
            ("stoploss", "decimal(16,8)", None),
            ("target_price", "decimal(16,8)", None),
            ("close_time", "bigint", None),
            ("registered_server_epoch", "bigint", None),
            ("registerer", "smallint", Some("UN")),
            ("is_long", "tinyint", Some("UN")),
            ("already_buy", "tinyint", Some("UN")),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
        }
        println!("Ok");
    }

    {
        // kelly_criterion
        print!("table 'kelly_criterion'...");
        io::stdout().flush();

        let table_name = String::from("kelly_criterion");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, UN, AI")),
            ("betting_rate", "double", None),
            ("win_rate", "double", None),
            ("lose_rate", "double", None),
            ("profit_rate", "double", None),
            ("loss_rate", "double", None),
        ];
        let table_condition = None;

        let insert_initial_columns = vec![
            "betting_rate",
            "win_rate",
            "lose_rate",
            "profit_rate",
            "loss_rate",
        ];
        let insert_initial_value = vec![
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
        ];
        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
            insert_one_record(&table_name, &insert_initial_columns, &insert_initial_value)
                .await
                .expect("Failed to insert initial row!");
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
            insert_one_record(&table_name, &insert_initial_columns, &insert_initial_value)
                .await
                .expect("Failed to insert initial row!");
        }

        println!("Ok");
    }

    {
        print!("table 'wallet'...");
        io::stdout().flush();

        let table_name = String::from("wallet");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("asset", "char(20)", None),
            ("free", "decimal(16,8)", None),
            ("locked", "decimal(16,8)", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");

        // table initialization for SIMUL MODE
        unsafe {
            if RUNNING_MODE == SIMUL {
                #[derive(Debug, FromRow)]
                struct Symbols {
                    symbol: String,
                }
                let fetch_table_name = String::from("valid_usdt_trades");
                let column_name = String::from("symbol");
                let condition = None;
                let mut symbols = Symbols {
                    symbol: String::new(),
                };
                let symbols_vec =
                    select_record(&fetch_table_name, &column_name, &condition, &symbols)
                        .await
                        .expect("Failed to fetch records!");
                let insert_table_name = String::from("wallet");
                let insert_columns = vec!["asset", "free", "locked"];
                let mut insert_values: Vec<Vec<String>> = Vec::new();
                let mut insert_value_container: Vec<String> = Vec::new();
                let mut symbol_truncated = String::new();

                insert_value_container.clear();
                insert_value_container.push(String::from("USDT"));
                insert_value_container.push(0.to_string());
                insert_value_container.push(0.to_string());
                insert_values.push(insert_value_container.clone());

                for mut element in symbols_vec {
                    insert_value_container.clear();
                    symbol_truncated.clear();
                    element.symbol.pop();
                    element.symbol.pop();
                    element.symbol.pop();
                    element.symbol.pop();
                    insert_value_container.push(element.symbol);
                    insert_value_container.push(0.to_string());
                    insert_value_container.push(0.to_string());
                    insert_values.push(insert_value_container.clone());
                }
                insert_records(&insert_table_name, &insert_columns, &insert_values).await;
            }
        }

        println!("Ok");
    }

    {
        print!("table 'wallet_testnet'...");
        io::stdout().flush();

        let table_name = String::from("wallet_testnet");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("asset", "char(20)", None),
            ("free", "decimal(16,8)", None),
            ("locked", "decimal(16,8)", None),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");

        println!("Ok");
    }

    {
        // sell_history
        print!("table 'sell_history'...");
        io::stdout().flush();

        let table_name = String::from("sell_history");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("symbol", "char(20)", None),
            ("soldtime", "bigint", None),
            ("used_usdt", "decimal(16,8)", None),
            ("get_usdt", "decimal(16,8)", None),
            ("buy_price", "decimal(16,8)", None),
            ("sell_price", "decimal(16,8)", None),
            ("base_qty", "decimal(16,8)", None),
            ("pure_profit_percent", "double", None),
            ("pure_profit_usdt", "decimal(16,8)", None),
            ("registerer", "smallint", Some("UN")),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }
        // else {
        //     delete_all_rows(&table_name)
        //         .await
        //         .expect("Failed to delete rows!");
        // }
        println!("Ok");
    }

    {
        // asset_manage_announcement
        print!("table 'asset_manage_announcement'...");
        io::stdout().flush();

        let table_name = String::from("asset_manage_announcement");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, UN, AI")),
            ("initial_usdt", "decimal(16,8)", None),
            ("current_total_usdt", "decimal(16,8)", None),
            ("profit", "decimal(16,8)", None),
            ("realtime_expected_total_usdt", "double", None),
            ("realtime_profit", "double", None),
            ("available_usdt", "decimal(16,8)", Some("UN")),
            ("is_tradable", "tinyint", Some("UN")),
            ("unit_trade_usdt", "decimal(16,8)", None),
        ];
        let table_condition = None;

        let insert_initial_columns = vec![
            "initial_usdt",
            "current_total_usdt",
            "profit",
            "realtime_expected_total_usdt",
            "realtime_profit",
            "available_usdt",
            "is_tradable",
            "unit_trade_usdt",
        ];
        let insert_initial_value = vec![
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
            String::from("0.0"),
        ];
        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
            insert_one_record(&table_name, &insert_initial_columns, &insert_initial_value)
                .await
                .expect("Failed to insert initial row!");
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
            insert_one_record(&table_name, &insert_initial_columns, &insert_initial_value)
                .await
                .expect("Failed to insert initial row!");
        }

        unsafe {
            if RUNNING_MODE == SIMUL {
                assets_managing_team::add_extra_usdt(dec!(10000000.0)).await;
                assets_managing_team::update_current_total_usdt().await;
            } else {
                let mut table_name = String::new();
                let column = String::from("free");
                let condition = Some(String::from("WHERE asset = 'USDT'"));

                #[derive(FromRow)]
                struct OneDecimal {
                    free: Decimal,
                };

                let data_struct = OneDecimal {
                    free: Decimal::new(0, 8),
                };

                order_team::account_information(&client).await;

                if RUNNING_MODE == TEST {
                    table_name = String::from("wallet_testnet");
                } else if RUNNING_MODE == REAL {
                    table_name = String::from("wallet");
                }

                let result = select_record(&table_name, &column, &condition, &data_struct)
                    .await
                    .unwrap();
                let free_usdt = result.first().unwrap().free;
                assets_managing_team::add_extra_usdt(free_usdt).await;
                assets_managing_team::update_current_total_usdt().await;
            }
        }
        assets_managing_team::update_kelly_criterion().await;
        assets_managing_team::set_available_usdt().await;
        assets_managing_team::set_unit_usdt().await;
        assets_managing_team::set_is_tradable().await;

        println!("Ok");
    }

    {
        // filtered_indices
        print!("table 'filtered_indices'...");
        io::stdout().flush();

        let table_name = String::from("filtered_indices");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI")),
            ("server_epoch", "bigint", Some("UN")),
            ("total_24h_change_profit_index", "double", None),
            ("usdt_24h_change_profit_index", "double", None),
            ("total_price_down_dist_index", "double", None),
            ("total_price_down_dist_index_maximum", "double", None),
            ("total_price_down_dist_index_flag", "integer", None),
        ];
        let initial_columns = vec![
            "server_epoch",
            "total_24h_change_profit_index",
            "usdt_24h_change_profit_index",
            "total_price_down_dist_index",
            "total_price_down_dist_index_maximum",
            "total_price_down_dist_index_flag",
        ];
        let initial_values = vec![
            String::from("0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        delete_all_rows(&table_name)
            .await
            .expect("Failed to delete rows!");
        insert_one_record(&table_name, &initial_columns, &initial_values)
            .await
            .expect("Failed to insert initial record!");

        println!("Ok");
    }

    {
        // pre_suggested_coin_list
        print!("table 'pre_suggested_coin_list'...");
        io::stdout().flush();

        let table_name = String::from("pre_suggested_coin_list");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("symbol", "char(20)", None),
            ("close_time", "bigint", None),
            ("suggested_price", "decimal(16,8)", None),
            ("current_price", "decimal(16,8)", None),
            ("stoploss", "decimal(16,8)", None),
            ("target_price", "decimal(16,8)", None),
            ("registered_server_epoch", "bigint", None),
            ("profit_percent", "double", None),
            ("minimum_profit_percent", "double", None),
            ("maximum_profit_percent", "double", None),
            ("registerer", "smallint", Some("UN")),
            ("is_long", "tinyint", Some("UN")),
        ];
        // let table_condition = Some("ENGINE = MEMORY");
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
        }
        println!("Ok");
    }

    {
        // future_available_balance
        print!("table 'future_available_balance'...");
        io::stdout().flush();

        let table_name = String::from("future_available_balance");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("available_usdt", "decimal(16,8)", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
        }

        let initial_columns = vec!["available_usdt"];
        let initial_values = vec![String::from("0.0")];
        insert_one_record(&table_name, &initial_columns, &initial_values)
        .await
        .expect("Failed to insert initial record!");
        println!("Ok");
    }

    {
        // future_ordered_coin_list
        print!("table 'future_ordered_coin_list'...");
        io::stdout().flush();

        let table_name = String::from("future_ordered_coin_list");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("order_type", "char(20)", None),   // POSITIONING, CLOSING
            ("status", "char(20)", None),   // LISTUP, FILLED, PARTIALLY_FILLED
            ("symbol", "char(20)", None),
            ("order_id", "bigint", Some("UN")),
            ("position", "char(20)", None),
            ("registered_server_epoch", "bigint", None),
            ("transact_time", "bigint", None),
            ("close_time", "bigint", None),
            ("used_usdt", "decimal(16,8)", None),
            ("expected_get_usdt", "double", None),
            ("pnl", "double", None),
            ("entry_price", "decimal(16,8)", None),
            ("current_price", "decimal(16,8)", None),
            ("base_qty_ordered", "decimal(16,8)", None),
            ("pure_profit_percent", "double", None),
            ("minimum_profit_percent", "double", None),
            ("maximum_profit_percent", "double", None),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        println!("Ok");
    }

    {
        // buy_ordered_coin_list
        print!("table 'buy_ordered_coin_list'...");
        io::stdout().flush();

        let table_name = String::from("buy_ordered_coin_list");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("symbol", "char(20)", None),
            ("order_id", "bigint", Some("UN")),
            ("transact_time", "bigint", None),
            ("close_time", "bigint", None),
            ("status", "char(20)", None),
            ("used_usdt", "decimal(16,8)", None),
            ("expected_get_usdt", "double", None),
            ("expected_usdt_profit", "double", None),
            ("buy_price", "decimal(16,8)", None),
            ("current_price", "decimal(16,8)", None),
            ("stoploss", "decimal(16,8)", None),
            ("target_price", "decimal(16,8)", None),
            ("base_qty_ordered", "decimal(16,8)", None),
            ("base_qty_fee_adjusted", "decimal(16,8)", None),
            ("pure_profit_percent", "double", None),
            ("minimum_profit_percent", "double", None),
            ("maximum_profit_percent", "double", None),
            // ("sell_count", "smallint", Some("UN")),
            ("registerer", "smallint", Some("UN")),
            ("is_long", "tinyint", Some("UN")),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        // // delete records tagged SIMUL
        // if RUNNING_MODE == SIMUL {
        //     let select_table_name = String::from("buy_ordered_coin_list");
        //     let select_columns = String::from("*");
        //     let select_condition = Some(String::from("WHERE status = 'SIMUL'"));
        //     let data_struct = BuyOrderedCoinList {
        //         id: 0,
        //         symbol: String::new(),
        //         order_id: 0,
        //         transact_time: 0,
        //         status: String::new(),
        //         used_usdt: Decimal::new(0, 8),
        //         expected_get_usdt: 0.0,
        //         expected_usdt_profit: 0.0,
        //         buy_price: Decimal::new(0, 8),
        //         current_price: Decimal::new(0, 8),
        //         base_qty_ordered: Decimal::new(0, 8),
        //         base_qty_fee_adjusted: Decimal::new(0, 8),
        //         pure_profit_percent: 0.0,
        //         minimum_profit_percent: 0.0,
        //         maximum_profit_percent: 0.0,
        //         registerer: 0,
        //         is_long: 0
        //     };

        //     let select_result = try_select_record(&select_table_name, &select_columns, &select_condition, &data_struct).await.unwrap();

        //     if !select_result.is_empty() {
        //         for element in select_result {
        //             let mut condition = String::from("WHERE id=");
        //             condition.push_str(element.id.to_string().as_str());
        //             delete_record(&select_table_name, &condition).await;
        //         }
        //     }
        // }
        println!("Ok");
    }

    {
        // sell_ordered_coin_list
        print!("table 'sell_ordered_coin_list'...");
        io::stdout().flush();

        let table_name = String::from("sell_ordered_coin_list");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("symbol", "char(20)", None),
            ("buy_order_id", "bigint", Some("UN")),
            ("sell_order_id", "bigint", Some("UN")),
            ("transact_time", "bigint", None),
            ("close_time", "bigint", None),
            ("status", "char(20)", None),
            ("used_usdt", "decimal(16,8)", None),
            ("get_usdt", "decimal(16,8)", None),
            ("get_usdt_fee_adjusted", "decimal(16,8)", None),
            ("buy_price", "decimal(16,8)", None),
            ("sell_price", "decimal(16,8)", None),
            ("stoploss", "decimal(16,8)", None),
            ("target_price", "decimal(16,8)", None),
            ("base_qty_ordered", "decimal(16,8)", None),
            ("pure_profit_percent", "decimal(16,8)", None),
            ("maximum_profit_percent", "double", None),
            // ("sell_count", "smallint", Some("UN")),
            ("registerer", "smallint", Some("UN")),
            ("is_long", "tinyint", Some("UN")),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
        }

        // delete records tagged SIMUL
        unsafe {
            if RUNNING_MODE == SIMUL {
                let select_table_name = String::from("sell_ordered_coin_list");
                let select_columns = String::from("*");
                let select_condition = Some(String::from("WHERE status = 'SIMUL'"));
                let data_struct = SellOrderedCoinList {
                    id: 0,
                    symbol: String::new(),
                    buy_order_id: 0,
                    sell_order_id: 0,
                    transact_time: 0,
                    close_time: 0,
                    status: String::new(),
                    used_usdt: Decimal::new(0, 8),
                    get_usdt: Decimal::new(0, 8),
                    get_usdt_fee_adjusted: Decimal::new(0, 8),
                    buy_price: Decimal::new(0, 8),
                    sell_price: Decimal::new(0, 8),
                    stoploss: Decimal::new(0, 8),
                    target_price: Decimal::new(0, 8),
                    base_qty_ordered: Decimal::new(0, 8),
                    pure_profit_percent: Decimal::new(0, 8),
                    maximum_profit_percent: 0.0,
                    // sell_count: 0,
                    registerer: 0,
                    is_long: 0,
                };

                let select_result = try_select_record(
                    &select_table_name,
                    &select_columns,
                    &select_condition,
                    &data_struct,
                )
                .await
                .unwrap();

                if !select_result.is_empty() {
                    for element in select_result {
                        let mut condition = String::from("WHERE id=");
                        condition.push_str(element.id.to_string().as_str());
                        delete_record(&select_table_name, &condition).await;
                    }
                }
            }
        }
        println!("Ok");
    }

    {
        // scoreboard
        print!("table 'scoreboard'...");
        io::stdout().flush();

        let table_name = String::from("scoreboard");
        let exists_result = exists_table(&table_name).await;
        let initial_table = vec![
            ("id", "integer", Some("PK, AI, UN")),
            ("total_number_of_coin", "integer", Some("UN")),
            ("pos_profit_number", "integer", Some("UN")),
            ("neg_profit_number", "integer", Some("UN")),
            ("total_used_usdt", "double", None),
            ("pos_used_usdt", "double", None),
            ("neg_used_usdt", "double", None),
            ("total_pos_profit_usdt", "double", None),
            ("total_neg_profit_usdt", "double", None),
            ("maximum_total_pos_profit_usdt", "double", None),
            ("avg_neg_profit_percent", "double", None),
            ("pos_liquidation_signal", "integer", Some("UN")),
            ("neg_liquidation_signal", "integer", Some("UN")),
            ("comment", "char(10)", None),
        ];
        let initial_columns = vec![
            "total_number_of_coin",
            "pos_profit_number",
            "neg_profit_number",
            "total_used_usdt",
            "pos_used_usdt",
            "neg_used_usdt",
            "total_pos_profit_usdt",
            "total_neg_profit_usdt",
            "maximum_total_pos_profit_usdt",
            "avg_neg_profit_percent",
            "pos_liquidation_signal",
            "neg_liquidation_signal",
            "comment",
        ];
        let initial_values = vec![
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
            String::from("0"),
            String::from("for_short"),
        ];
        let initial_values2 = vec![
            String::from("0"),
            String::from("0"),
            String::from("0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0.0"),
            String::from("0"),
            String::from("0"),
            String::from("for_long"),
        ];
        let table_condition = None;

        if exists_result == false {
            let mut result = new_table(&table_name, &initial_table, &table_condition).await;
            if result.is_err() {
                loop {
                    result = new_table(&table_name, &initial_table, &table_condition).await;
                    if result.is_ok() {
                        insert_one_record(&table_name, &initial_columns, &initial_values)
                            .await
                            .expect("Failed to insert initial record!");
                        insert_one_record(&table_name, &initial_columns, &initial_values2)
                            .await
                            .expect("Failed to insert initial record!");
                        break;
                    }
                    sleep(Duration::from_millis(10)).await;
                }
            }
            insert_one_record(&table_name, &initial_columns, &initial_values)
                .await
                .expect("Failed to insert initial record!");
            insert_one_record(&table_name, &initial_columns, &initial_values2)
                .await
                .expect("Failed to insert initial record!");
        } else {
            delete_all_rows(&table_name)
                .await
                .expect("Failed to delete rows!");
            insert_one_record(&table_name, &initial_columns, &initial_values)
                .await
                .expect("Failed to insert initial record!");
            insert_one_record(&table_name, &initial_columns, &initial_values2)
                .await
                .expect("Failed to insert initial record!");
        }
        println!("Ok");
    }
}
