// Focused clipboard-read coverage for the client keyboard helper surface.
//
// Scope: isolate clipboard command and fallback reader behavior so the
// keyboard extra contract stays below the hygiene size cap.
// Targets: `client/src/input/keyboard.rs`.
// Why: clipboard sourcing must stay predictable across operator overrides,
// fallback tools, and coverage-mode shells.

mod keymap {
    pub use lesavka_client::input::keymap::*;
}

#[allow(warnings)]
mod keyboard_clipboard_contract {
    include!(env!("LESAVKA_CLIENT_KEYBOARD_SRC"));

    use serial_test::serial;
    use std::fs;
    use std::os::unix::fs::PermissionsExt;
    use std::path::Path;
    use temp_env::with_var;
    use tempfile::tempdir;

    fn write_executable(dir: &Path, name: &str, body: &str) {
        let path = dir.join(name);
        fs::write(&path, body).expect("write script");
        let mut perms = fs::metadata(&path).expect("metadata").permissions();
        perms.set_mode(0o755);
        fs::set_permissions(path, perms).expect("chmod");
    }

    fn with_fake_path_command(name: &str, script_body: &str, f: impl FnOnce()) {
        let dir = tempdir().expect("tempdir");
        write_executable(dir.path(), name, script_body);
        let prior = std::env::var("PATH").unwrap_or_default();
        let merged = if prior.is_empty() {
            dir.path().display().to_string()
        } else {
            format!("{}:{prior}", dir.path().display())
        };
        with_var("PATH", Some(merged), f);
    }

    #[test]
    #[serial]
    fn read_clipboard_text_uses_fallback_tool_when_available() {
        let wl_paste = "#!/usr/bin/env sh\nprintf 'fallback-clipboard'\n";
        with_var("LESAVKA_CLIPBOARD_CMD", None::<&str>, || {
            with_fake_path_command("wl-paste", wl_paste, || {
                let text = read_clipboard_text().expect("fallback clipboard text");
                assert_eq!(text, "fallback-clipboard");
            });
        });
    }

    #[test]
    #[serial]
    fn read_clipboard_text_returns_none_when_command_is_empty_and_fallback_fails() {
        let empty_path = tempdir().expect("tempdir");
        temp_env::with_vars(
            [
                ("LESAVKA_CLIPBOARD_CMD", Some("printf ''")),
                ("PATH", empty_path.path().to_str()),
            ],
            || {
                with_fake_path_command("wl-paste", "#!/usr/bin/env sh\nexit 1\n", || {
                    assert!(read_clipboard_text().is_none());
                });
            },
        );
    }

    #[test]
    #[cfg(coverage)]
    #[serial]
    fn read_clipboard_text_prefers_nonempty_command_output_in_coverage() {
        with_var(
            "LESAVKA_CLIPBOARD_CMD",
            Some("printf 'coverage-clipboard'"),
            || {
                let text = read_clipboard_text().expect("coverage clipboard text");
                assert_eq!(text, "coverage-clipboard");
            },
        );
    }

    #[test]
    #[cfg(coverage)]
    #[serial]
    fn read_clipboard_text_ignores_failed_command_even_with_stdout() {
        let dir = tempdir().expect("tempdir");
        write_executable(
            dir.path(),
            "sh",
            "#!/bin/sh\nprintf 'stale-clipboard'\nexit 1\n",
        );
        temp_env::with_vars(
            [
                ("LESAVKA_CLIPBOARD_CMD", Some("ignored")),
                ("PATH", dir.path().to_str()),
            ],
            || {
                assert!(read_clipboard_text().is_none());
            },
        );
    }

    #[test]
    #[cfg(coverage)]
    #[serial]
    fn read_clipboard_text_tolerates_missing_shell_in_coverage() {
        let dir = tempdir().expect("tempdir");
        with_var(
            "LESAVKA_CLIPBOARD_CMD",
            Some("printf 'coverage-clipboard'"),
            || {
                with_var(
                    "PATH",
                    Some(dir.path().to_string_lossy().to_string()),
                    || {
                        assert!(read_clipboard_text().is_none());
                    },
                );
            },
        );
    }
}
