use fidc_core::DataSet;
use std::fs;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};

fn temp_dir() -> PathBuf {
    let uniq = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("clock")
        .as_nanos();
    let dir = std::env::temp_dir().join(format!("fidc-bt-partitioned-{uniq}"));
    fs::create_dir_all(&dir).expect("mkdir temp");
    dir
}

#[test]
fn can_load_partitioned_snapshot_dir() {
    let dir = temp_dir();
    fs::create_dir_all(dir.join("benchmark/2024/01")).unwrap();
    fs::create_dir_all(dir.join("market/2024/01")).unwrap();
    fs::create_dir_all(dir.join("factors/2024/01")).unwrap();
    fs::create_dir_all(dir.join("candidates/2024/01")).unwrap();
    fs::create_dir_all(dir.join("corporate_actions/2024/01")).unwrap();

    fs::write(
        dir.join("instruments.csv"),
        "symbol,name,board,round_lot,listed_at,delisted_at,status\n000001.SZ,PingAn,SZ,100,2020-01-01,,active\n",
    )
    .unwrap();
    fs::write(
        dir.join("benchmark/2024/01/2024-01-02.csv"),
        "date,benchmark,open,close,prev_close,volume\n2024-01-02,CSI300.DEMO,2990,3000,2980,100000000\n",
    )
    .unwrap();
    fs::write(
        dir.join("market/2024/01/2024-01-02.csv"),
        "date,symbol,open,high,low,close,prev_close,volume,paused,upper_limit,lower_limit,day_open,last_price,bid1,ask1,price_tick\n2024-01-02,000001.SZ,10,10.5,9.9,10.2,10,100000,false,11,9,10.1,10.15,10.14,10.16,0.01\n",
    )
    .unwrap();
    fs::write(
        dir.join("factors/2024/01/2024-01-02.csv"),
        "date,symbol,market_cap_bn,free_float_cap_bn,pe_ttm,turnover_ratio,effective_turnover_ratio\n2024-01-02,000001.SZ,40,35,12,3.2,2.1\n",
    )
    .unwrap();
    fs::write(
        dir.join("candidates/2024/01/2024-01-02.csv"),
        "date,symbol,is_st,is_new_listing,is_paused,allow_buy,allow_sell,is_kcb,is_one_yuan\n2024-01-02,000001.SZ,false,false,false,true,true,false,false\n",
    )
    .unwrap();
    fs::write(
        dir.join("corporate_actions/2024/01/2024-01-02.csv"),
        "date,symbol,payable_date,share_cash,share_bonus,share_gift,issue_quantity,issue_price,reform,adjust_factor\n2024-01-02,000001.SZ,2024-01-05,0.5,0.1,0.0,0,0,false,1.05\n",
    )
    .unwrap();

    let data = DataSet::from_partitioned_dir(&dir).expect("partitioned dataset");
    assert_eq!(data.benchmark_code(), "CSI300.DEMO");
    assert!(
        data.market_snapshots_on(chrono::NaiveDate::from_ymd_opt(2024, 1, 2).unwrap())
            .len()
            == 1
    );
    let market_rows =
        data.market_snapshots_on(chrono::NaiveDate::from_ymd_opt(2024, 1, 2).unwrap());
    let snapshot = market_rows.first().expect("market snapshot");
    assert_eq!(snapshot.day_open, 10.1);
    assert_eq!(snapshot.last_price, 10.15);
    assert_eq!(snapshot.price_tick, 0.01);
    assert_eq!(
        data.instruments()
            .get("000001.SZ")
            .expect("instrument")
            .round_lot,
        100
    );
    assert_eq!(
        data.instruments()
            .get("000001.SZ")
            .expect("instrument")
            .listed_at,
        Some(chrono::NaiveDate::from_ymd_opt(2020, 1, 1).unwrap())
    );
    let actions = data.corporate_actions_on(chrono::NaiveDate::from_ymd_opt(2024, 1, 2).unwrap());
    assert_eq!(actions.len(), 1);
    assert_eq!(
        actions[0].payable_date,
        Some(chrono::NaiveDate::from_ymd_opt(2024, 1, 5).unwrap())
    );
    assert!((actions[0].share_cash - 0.5).abs() < 1e-9);
    assert!((actions[0].split_ratio() - 1.1).abs() < 1e-9);

    let _ = fs::remove_dir_all(&dir);
}
