use std::io::{Read, Write};
use std::path::Path;

use crate::hook::{post_tool, pre_tool, session};
use crate::policy::loader::load_policy_or_defaults;
use crate::threat::killer::terminate_session;
use crate::types::HookInput;

/// Main hook entry point. Reads JSON from stdin, dispatches to the right handler.
pub fn run(event: &str) -> i32 {
    // Read stdin
    let mut input_str = String::new();
    if let Err(e) = std::io::stdin().read_to_string(&mut input_str) {
        eprintln!("railyard: failed to read stdin: {}", e);
        return 0; // Don't block on read errors
    }

    // Parse input
    let input: HookInput = match serde_json::from_str(&input_str) {
        Ok(i) => i,
        Err(e) => {
            eprintln!("railyard: failed to parse hook input: {}", e);
            return 0; // Don't block on parse errors
        }
    };

    // Load policy
    let cwd = Path::new(&input.cwd);
    let policy = load_policy_or_defaults(cwd);

    // Dispatch
    match event {
        "PreToolUse" => {
            let result = pre_tool::handle(&input, &policy);

            // Write output to stdout
            if let Ok(json) = serde_json::to_string(&result.output) {
                let _ = std::io::stdout().write_all(json.as_bytes());
                let _ = std::io::stdout().write_all(b"\n");
                let _ = std::io::stdout().flush();
            }

            // If termination requested, flush output first then kill
            if let Some(req) = result.terminate {
                let state_dir = cwd.join(".railyard/state");
                let trace_dir = cwd.join(&policy.trace.directory);
                let mut state = req.state;
                terminate_session(&mut state, &req.tier, &req.command, &state_dir, &trace_dir);
                // terminate_session sends SIGTERM to parent — exit cleanly
                std::process::exit(0);
            }

            0
        }
        "PostToolUse" => {
            post_tool::handle(&input, &policy);
            0
        }
        "SessionStart" => {
            session::handle(&input, &policy);
            0
        }
        _ => {
            eprintln!("railyard: unknown event: {}", event);
            0
        }
    }
}
