use es_public_proxy::parse::{ScrollBody, SearchBody};
use es_public_proxy::{filter_request, ProxyConfig};
use std::ffi::OsStr;
use std::fs;

mod common;

#[test]
fn basic_load() {
    let parts = common::load_parts(std::path::Path::new("tests/files/search/GET_search.txt"));
    assert_eq!(parts.method, "GET");
    assert_eq!(parts.path_and_query, "/some-index/_search");
}

#[test]
fn parse_search_bodies() {
    let file_paths = fs::read_dir("tests/files/search").unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        let parts = common::load_parts(&path);
        if let Some(body) = parts.body {
            println!("parsing: {}", path.display());
            println!("BODY: {}", body);
            let parsed: SearchBody = serde_json::from_str(&body).unwrap();
            let raw_val: serde_json::Value = serde_json::from_str(&body).unwrap();
            assert_eq!(raw_val, serde_json::to_value(parsed).unwrap());
        }
    }
}

#[test]
fn parse_scroll_bodies() {
    let file_paths = fs::read_dir("tests/files/scroll").unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        let parts = common::load_parts(&path);
        if let Some(body) = parts.body {
            println!("  parsing: {}", path.display());
            //println!("BODY: {}", body);
            let _parsed: ScrollBody = serde_json::from_str(&body).unwrap();
        }
    }
}

#[test]
fn filter_search_requests() {
    let file_paths = fs::read_dir("tests/files/search").unwrap();
    let mut config = ProxyConfig::default();
    config.unsafe_all_indices = Some(true);
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        rt.block_on(filter_request(req, &config)).unwrap();
    }
}

#[test]
fn filter_scroll_requests() {
    let file_paths = fs::read_dir("tests/files/scroll").unwrap();
    let mut config = ProxyConfig::default();
    config.unsafe_all_indices = Some(true);
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        rt.block_on(filter_request(req, &config)).unwrap();
    }
}

#[test]
fn filter_other_requests() {
    let file_paths = fs::read_dir("tests/files/other").unwrap();
    let mut config = ProxyConfig::default();
    config.unsafe_all_indices = Some(true);
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        rt.block_on(filter_request(req, &config)).unwrap();
    }
}

#[test]
fn filter_failures() {
    let file_paths = fs::read_dir("tests/files/search_fail").unwrap();
    let mut config = ProxyConfig::default();
    config.unsafe_all_indices = Some(true);
    let mut rt = tokio::runtime::Runtime::new().unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        let result = rt.block_on(filter_request(req, &config));
        assert!(result.is_err());
    }

    let file_paths = fs::read_dir("tests/files/scroll_fail").unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        let result = rt.block_on(filter_request(req, &config));
        assert!(result.is_err());
    }

    let file_paths = fs::read_dir("tests/files/other_fail").unwrap();

    for path in file_paths {
        let path = path.unwrap().path();
        if path.extension() != Some(OsStr::new("txt")) {
            continue;
        }
        println!("  filtering: {}", path.display());
        let req = common::load_request(&path);
        let result = rt.block_on(filter_request(req, &config));
        assert!(result.is_err());
    }
}
