pub mod error_code {
    pub const COMMAND_EMPTY: u32 = 1;
    pub const CWD_NOT_FOUND: u32 = 2;
    pub const CWD_NOT_DIRECTORY: u32 = 3;
    pub const TIMEOUT_INVALID: u32 = 4;
    pub const TIMEOUT_EXCEEDS_MAX: u32 = 5;
    pub const INTERACTIVE_COMMAND: u32 = 6;
}

use agent_contracts::backend::{PathKind, PathStat};

use super::constants::max_timeout_ms;
use super::input::BashInput;

#[derive(Debug, Clone)]
pub struct ValidationResult {
    pub result: bool,
    pub message: Option<String>,
    pub error_code: Option<u32>,
}

impl ValidationResult {
    pub fn ok() -> Self {
        Self {
            result: true,
            message: None,
            error_code: None,
        }
    }

    pub fn error(message: impl Into<String>, error_code: u32) -> Self {
        Self {
            result: false,
            message: Some(message.into()),
            error_code: Some(error_code),
        }
    }
}

pub fn validate_command(input: &BashInput) -> ValidationResult {
    if input.command.trim().is_empty() {
        return ValidationResult::error("Command cannot be empty", error_code::COMMAND_EMPTY);
    }

    ValidationResult::ok()
}

pub fn validate_timeout(input: &BashInput) -> ValidationResult {
    let Some(timeout) = input.timeout else {
        return ValidationResult::ok();
    };

    if timeout == 0 {
        return ValidationResult::error(
            "Timeout must be greater than 0 milliseconds",
            error_code::TIMEOUT_INVALID,
        );
    }

    let max_timeout = max_timeout_ms();
    if timeout > max_timeout {
        return ValidationResult::error(
            format!(
                "Timeout {}ms exceeds maximum allowed {}ms",
                timeout, max_timeout
            ),
            error_code::TIMEOUT_EXCEEDS_MAX,
        );
    }

    ValidationResult::ok()
}

pub fn validate_cwd_backend(cwd: &str, stat: &PathStat) -> ValidationResult {
    if !stat.exists {
        return ValidationResult::error(
            format!("Working directory does not exist: {}", cwd),
            error_code::CWD_NOT_FOUND,
        );
    }

    if stat.kind != Some(PathKind::Directory) {
        return ValidationResult::error(
            format!("Working directory is not a directory: {}", cwd),
            error_code::CWD_NOT_DIRECTORY,
        );
    }

    ValidationResult::ok()
}