use biolib::parse_resource_uri;

#[test]
fn parse_simple_uri() {
    let uri = parse_resource_uri("dev/model").unwrap();
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
    assert!(uri.resource_prefix.is_none());
    assert!(uri.version.is_none());
    assert!(uri.tag.is_none());
}

#[test]
fn parse_uri_with_version() {
    let uri = parse_resource_uri("dev/model:1.0.0").unwrap();
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
    let v = uri.version.unwrap();
    assert_eq!(v.major, 1);
    assert_eq!(v.minor, 0);
    assert_eq!(v.patch, 0);
}

#[test]
fn parse_uri_with_prefix() {
    let uri = parse_resource_uri("@biolib.com/dev/model").unwrap();
    assert_eq!(uri.resource_prefix.as_deref(), Some("biolib.com"));
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
}

#[test]
fn parse_uri_with_prefix_and_version() {
    let uri = parse_resource_uri("@biolib.com/dev/model:1.0.0").unwrap();
    assert_eq!(uri.resource_prefix.as_deref(), Some("biolib.com"));
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
    assert!(uri.version.is_some());
}

#[test]
fn parse_uri_with_tag() {
    let uri = parse_resource_uri("dev/model:latest").unwrap();
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
    assert_eq!(uri.tag.as_deref(), Some("latest"));
    assert!(uri.version.is_none());
}

#[test]
fn parse_uri_with_wildcard_version() {
    let uri = parse_resource_uri("dev/model:*").unwrap();
    assert_eq!(uri.account_handle, "dev");
    assert_eq!(uri.resource_name.as_deref(), Some("model"));
    assert!(uri.version.is_none());
    assert!(uri.tag.is_none());
}

#[test]
fn parse_account_only() {
    let uri = parse_resource_uri("dev").unwrap();
    assert_eq!(uri.account_handle, "dev");
    assert!(uri.resource_name.is_none());
}

#[test]
fn normalized_names() {
    let uri = parse_resource_uri("My-Team/My-App").unwrap();
    assert_eq!(uri.account_handle, "My-Team");
    assert_eq!(uri.account_handle_normalized, "my_team");
    assert_eq!(uri.resource_name.as_deref(), Some("My-App"));
}

#[test]
fn reject_double_slash_in_path() {
    assert!(parse_resource_uri("dev/model/extra").is_err());
}

#[test]
fn reject_empty_prefix() {
    assert!(parse_resource_uri("@/dev/model").is_err());
}

#[test]
fn reject_invalid_version() {
    assert!(parse_resource_uri("dev/model:1.2").is_err());
}

#[test]
fn reject_url_with_wrong_prefix() {
    assert!(parse_resource_uri("@bib.com/DTU/DeepTMHMM:1.0.42").is_ok());
    assert!(parse_resource_uri("dev/model:INVALID_TAG").is_err());
}

#[test]
fn uri_sample_json_positive() {
    let expected = vec![
        "dev/model",
        "dev/model:1.0.0",
        "@biolib.com/dev/model",
        "@biolib.com/dev/model:1.0.0",
    ];

    let test_groups: Vec<Vec<&str>> = vec![
        vec!["dev/model"],
        vec!["dev/model:1.0.0"],
        vec!["@biolib.com/dev/model"],
        vec!["@biolib.com/dev/model:1.0.0"],
    ];

    for (group, expected_str) in test_groups.iter().zip(expected.iter()) {
        for test_input in group {
            let uri = parse_resource_uri(test_input)
                .unwrap_or_else(|_| panic!("Failed to parse: {test_input}"));
            let reconstructed = format_uri(&uri);
            assert_eq!(
                &reconstructed, expected_str,
                "Input '{test_input}' expected '{expected_str}', got '{reconstructed}'"
            );
        }
    }
}

fn format_uri(uri: &biolib::ResourceUri) -> String {
    let mut result = String::new();
    if let Some(ref prefix) = uri.resource_prefix {
        result.push('@');
        result.push_str(prefix);
        result.push('/');
    }
    result.push_str(&uri.account_handle);
    if let Some(ref name) = uri.resource_name {
        result.push('/');
        result.push_str(name);
    }
    if let Some(ref version) = uri.version {
        result.push(':');
        result.push_str(&version.to_string());
    }
    if let Some(ref tag) = uri.tag {
        result.push(':');
        result.push_str(tag);
    }
    result
}
