use super::*;
use crate::config::FeatureCandidate;

#[test]
fn forwards_provider_model_and_optional_project_id() {
    let (port, request) = spawn_server(
        r#"{"text":"ok","model":"qwen/qwen3.6-35b-a3b","usage":{"input_tokens":3,"output_tokens":4,"total_tokens":7}}"#,
    );
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(Some("project-123"));
    cfg.bindings.text_generate.provider = Some("local:lm-studio".to_string());
    cfg.bindings.text_generate.model = Some("qwen/qwen3.6-35b-a3b".to_string());

    let result = generate_via_daemon_with_max_tokens(
        &cfg,
        "Write a title",
        Some("Be brief"),
        Some(64),
        None,
    )
    .unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert!(request.starts_with("POST /api/llm/generate HTTP/1.1"));
    assert_eq!(body["provider"], "local:lm-studio");
    assert_eq!(body["model"], "qwen/qwen3.6-35b-a3b");
    assert_eq!(body["project_id"], "project-123");
    assert_eq!(body["prompt"], "Write a title");
    assert_eq!(body["system_prompt"], "Be brief");
    assert!(body.get("system").is_none());
    assert!(body.get("profile").is_none());
    assert_eq!(body["max_tokens"], 64);
    assert_eq!(result.text, "ok");
    assert_eq!(
        result.usage.as_ref().and_then(|usage| usage.token_count()),
        Some(7)
    );

    let (port, request) = spawn_server(r#"{"text":"ok"}"#);
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(None);
    cfg.bindings.text_generate.provider = Some("local:lm-studio".to_string());
    cfg.bindings.text_generate.model = Some("qwen/qwen3.6-35b-a3b".to_string());

    generate_via_daemon(&cfg, "No project", None).unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["provider"], "local:lm-studio");
    assert_eq!(body["model"], "qwen/qwen3.6-35b-a3b");
    assert!(body.get("project_id").is_none());
    assert!(body.get("profile").is_none());
}

#[test]
fn text_generation_defaults_to_feature_low_without_provider_model() {
    let (port, request) = spawn_server(r#"{"text":"ok"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(Some("project-123"));
    cfg.bindings.text_generate.provider = None;
    cfg.bindings.text_generate.model = None;

    generate_via_daemon(&cfg, "No provider", Some("Be brief")).unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["prompt"], "No provider");
    assert_eq!(body["system_prompt"], "Be brief");
    assert_eq!(body["profile"], "feature_low");
    assert!(body.get("provider").is_none());
    assert!(body.get("model").is_none());
    assert_eq!(body["project_id"], "project-123");
}

#[test]
fn configured_binding_profile_replaces_feature_low_default() {
    let (port, request) = spawn_server(r#"{"text":"ok"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(None);
    cfg.bindings.text_generate.provider = None;
    cfg.bindings.text_generate.model = None;
    cfg.bindings.text_generate.profile = Some("feature_high".to_string());

    generate_via_daemon(&cfg, "Configured profile", None).unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["profile"], "feature_high");
    assert!(body.get("provider").is_none());
    assert!(body.get("model").is_none());
}

#[test]
fn pinned_one_shot_forwards_explicit_candidates_and_omits_profile() {
    use crate::ai::generation::generate_one_shot_pinned;
    use crate::config::AiRouting;

    let (port, request) = spawn_server(r#"{"text":"ok","model":"claude-sonnet"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(Some("project-123"));
    // A configured binding profile/provider/model must not leak into a pinned
    // call: the explicit chain supersedes the whole binding.
    cfg.bindings.text_generate.provider = Some("local:lm-studio".to_string());
    cfg.bindings.text_generate.model = Some("qwen/qwen3.6-35b-a3b".to_string());
    cfg.bindings.text_generate.profile = Some("feature_low".to_string());
    let candidates = vec![
        FeatureCandidate {
            candidate: "claude/sonnet".to_string(),
            reasoning_effort: Some("xhigh".to_string()),
        },
        FeatureCandidate {
            candidate: "codex/gpt-5.5".to_string(),
            reasoning_effort: None,
        },
    ];

    let result = generate_one_shot_pinned(
        &cfg,
        AiRouting::Daemon,
        &candidates,
        "Pinned prompt",
        Some("Be brief"),
        Some(64),
    )
    .unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert!(request.starts_with("POST /api/llm/generate HTTP/1.1"));
    assert_eq!(
        body["candidates"],
        serde_json::json!([
            {"candidate":"claude/sonnet","reasoning_effort":"xhigh"},
            {"candidate":"codex/gpt-5.5"}
        ])
    );
    assert!(body.get("profile").is_none());
    assert!(body.get("provider").is_none());
    assert!(body.get("model").is_none());
    assert!(body.get("reasoning_effort").is_none());
    assert_eq!(body["prompt"], "Pinned prompt");
    assert_eq!(body["system_prompt"], "Be brief");
    assert_eq!(body["max_tokens"], 64);
    assert_eq!(body["project_id"], "project-123");
    assert_eq!(result.text, "ok");
}

#[test]
fn forwards_candidates_and_reasoning_effort_from_binding() {
    let (port, request) = spawn_server(r#"{"text":"ok","applied_reasoning_effort":"high"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(None);
    cfg.bindings.text_generate.provider = None;
    cfg.bindings.text_generate.model = None;
    cfg.bindings.text_generate.candidates = Some(vec![
        FeatureCandidate {
            candidate: "codex/gpt-5.5".to_string(),
            reasoning_effort: Some("high".to_string()),
        },
        FeatureCandidate {
            candidate: "droid/qwen3.6".to_string(),
            reasoning_effort: None,
        },
    ]);
    cfg.bindings.text_generate.reasoning_effort = Some("medium".to_string());

    let result =
        generate_via_daemon_with_max_tokens(&cfg, "Use candidates", None, None, None).unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["prompt"], "Use candidates");
    assert!(body.get("profile").is_none());
    assert_eq!(body["reasoning_effort"], "medium");
    assert_eq!(
        body["candidates"],
        serde_json::json!([
            {"candidate":"codex/gpt-5.5","reasoning_effort":"high"},
            {"candidate":"droid/qwen3.6"}
        ])
    );
    assert_eq!(result.applied_reasoning_effort.as_deref(), Some("high"));
}

#[test]
fn per_call_profile_overrides_configured_binding_profile() {
    let (port, request) = spawn_server(r#"{"text":"ok"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let mut cfg = test_context(None);
    cfg.bindings.text_generate.provider = None;
    cfg.bindings.text_generate.model = None;
    cfg.bindings.text_generate.profile = Some("feature_high".to_string());

    generate_via_daemon_with_max_tokens(&cfg, "Override profile", None, None, Some("feature_mid"))
        .unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["profile"], "feature_mid");
}

#[test]
fn explicit_provider_model_suppresses_profile_override() {
    let (port, request) = spawn_server(r#"{"text":"ok"}"#);
    let home = temp_home();
    let _env = EnvGuard::set_home(home.path());
    write_daemon_files(home.path(), port, "text-token");
    let cfg = test_context(None);

    generate_via_daemon_with_max_tokens(&cfg, "Explicit routing", None, None, Some("feature_mid"))
        .unwrap();
    let request = request.join().unwrap().unwrap();
    let body = request_body_json(&request);

    assert_eq!(body["provider"], "daemon-provider");
    assert_eq!(body["model"], "daemon-model");
    assert!(body.get("profile").is_none());
}
