use metacrate_grid_agent::{
    AgentPreferences, ConfigLoader, MapEnvironment, OperatingMode, OperatorScreen, OperatorTui,
    PreferencesPanel, TuiInput, TuiRenderOptions,
};
use std::fs;
use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH};

fn temporary(name: &str) -> PathBuf {
    let directory = std::env::temp_dir().join(format!(
        "metacrate-preferences-{}-{name}",
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_nanos()
    ));
    fs::create_dir_all(&directory).unwrap();
    directory
}

#[test]
fn yaml_is_primary_and_preferences_preserve_unknown_settings() {
    let directory = temporary("yaml");
    let path = directory.join("config.yml");
    fs::write(
        &path,
        r"schema_version: 1
integrated: true
llm:
  endpoint_url: https://ai.invalid/v1/chat/completions
  api_key: private-key
  model: local-model
grid:
  login_url: https://grid.invalid/login
  avatar_name: Service Avatar
  password: private-password
authorized_avatar_uuids:
  - 00000000-0000-4000-8000-000000000001
behavior:
  idle_interval_seconds: 321
",
    )
    .unwrap();
    let config = ConfigLoader::new()
        .with_file(&path)
        .with_environment(MapEnvironment::default())
        .load()
        .unwrap();
    assert_eq!(config.mode, OperatingMode::Integrated);
    assert_eq!(config.llm.model.as_deref(), Some("local-model"));
    assert_eq!(config.behavior.idle_interval.as_secs(), 321);

    let mut preferences = AgentPreferences::load(&path).unwrap();
    preferences.set_llm_model("replacement-model".into());
    preferences.save(&path).unwrap();
    let saved = fs::read_to_string(&path).unwrap();
    assert!(saved.contains("idle_interval_seconds: 321"));
    assert!(saved.contains("model: replacement-model"));
    assert!(!format!("{preferences:?}").contains("private-key"));
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt as _;
        assert_eq!(
            fs::metadata(&path).unwrap().permissions().mode() & 0o777,
            0o600
        );
    }
    fs::remove_dir_all(directory).unwrap();
}

#[test]
fn dotenv_import_is_explicit_and_preferences_panel_never_renders_secrets() {
    let directory = temporary("import");
    let dotenv = directory.join("legacy.env");
    let config = directory.join("config.yml");
    fs::write(
        &dotenv,
        "OPENAPI_URL=https://ai.invalid/v1/chat/completions\nOPENAPI_KEY=very-secret-key\nOPENAPI_MODEL=test-model\nGRID_LOGIN_URL=https://grid.invalid/login\nGRID_USER=Test Avatar\nGRID_PASSWORD=very-secret-password\n",
    )
    .unwrap();
    let mut preferences = AgentPreferences::load(&config).unwrap();
    preferences.import_dotenv(&dotenv).unwrap();
    preferences.set_privileged_users(vec!["00000000-0000-4000-8000-000000000001".into()]);
    preferences.save(&config).unwrap();

    let panel = PreferencesPanel::open(config.clone()).unwrap();
    let summary = panel.summary();
    assert_eq!(summary.llm_model.as_deref(), Some("test-model"));
    assert!(summary.llm_api_key_configured && summary.grid_password_configured);
    assert_eq!(summary.privileged_users.len(), 1);

    let mut tui = OperatorTui::with_preferences(config).unwrap();
    tui.screen = OperatorScreen::Preferences;
    let rendered = tui.render(TuiRenderOptions {
        width: 120,
        height: 30,
        color: false,
    });
    assert!(rendered.contains("LLM API key: [configured]"));
    assert!(rendered.contains("grid password: [configured]"));
    assert!(!rendered.contains("very-secret"));
    let _ = tui.reduce(TuiInput::PreferenceNext);
    let _ = tui.reduce(TuiInput::PreferenceEditOrCommit);
    for value in "https://replacement.invalid/v1/chat".chars() {
        let _ = tui.reduce(TuiInput::PreferenceCharacter(value));
    }
    let _ = tui.reduce(TuiInput::PreferenceEditOrCommit);
    let _ = tui.reduce(TuiInput::PreferenceSave);
    fs::remove_dir_all(directory).unwrap();
}
