use serde::{Deserialize, Serialize};

/// Command safety classification.
/// No full-auto mode — destructive commands ALWAYS require human approval (BMad must-have).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SafetyLevel {
    /// Read-only commands (ls, cat, kubectl get, aws describe-*)
    ReadOnly,
    /// Modifying but recoverable (restart service, scale replicas)
    Modifying,
    /// Destructive / irreversible (rm, drop, terminate, delete)
    Destructive,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Classification {
    pub command: String,
    pub safety: SafetyLevel,
    pub requires_approval: bool,
    pub reason: String,
    pub matched_pattern: Option<String>,
}

/// Classify a shell command by safety level.
/// Uses pattern matching (not regex on raw strings — BMad review finding).
pub fn classify(command: &str) -> Classification {
    let trimmed = command.trim();
    let tokens: Vec<&str> = trimmed.split_whitespace().collect();

    if tokens.is_empty() {
        return Classification {
            command: trimmed.to_string(),
            safety: SafetyLevel::ReadOnly,
            requires_approval: false,
            reason: "Empty command".into(),
            matched_pattern: None,
        };
    }

    let base_cmd = tokens[0];

    // --- Destructive patterns (always require approval) ---
    let destructive_patterns: &[(&str, &str)] = &[
        ("rm", "file deletion"),
        ("rmdir", "directory deletion"),
        ("dd", "raw disk write"),
        ("mkfs", "filesystem format"),
        ("fdisk", "partition table modification"),
        ("shutdown", "system shutdown"),
        ("reboot", "system reboot"),
        ("kill", "process termination"),
        ("pkill", "process termination"),
        ("killall", "process termination"),
    ];

    for (pattern, reason) in destructive_patterns {
        if base_cmd == *pattern {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Destructive,
                requires_approval: true,
                reason: reason.to_string(),
                matched_pattern: Some(pattern.to_string()),
            };
        }
    }

    // AWS destructive
    if base_cmd == "aws" {
        let has_destructive = tokens.iter().any(|t| {
            matches!(*t, "terminate-instances" | "delete-stack" | "delete-bucket"
                | "delete-table" | "delete-function" | "delete-cluster"
                | "delete-service" | "deregister-task-definition"
                | "delete-db-instance" | "delete-db-cluster")
        });
        if has_destructive {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Destructive,
                requires_approval: true,
                reason: "AWS resource deletion".into(),
                matched_pattern: Some("aws delete/terminate".into()),
            };
        }
    }

    // kubectl destructive
    if base_cmd == "kubectl" {
        let has_destructive = tokens.iter().any(|t| {
            matches!(*t, "delete" | "drain" | "cordon" | "taint")
        });
        if has_destructive {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Destructive,
                requires_approval: true,
                reason: "Kubernetes destructive operation".into(),
                matched_pattern: Some("kubectl delete/drain".into()),
            };
        }
    }

    // terraform destructive
    if base_cmd == "terraform" || base_cmd == "tofu" {
        let has_destructive = tokens.iter().any(|t| {
            matches!(*t, "destroy" | "apply")
        });
        if has_destructive {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Destructive,
                requires_approval: true,
                reason: "Infrastructure state change".into(),
                matched_pattern: Some("terraform destroy/apply".into()),
            };
        }
    }

    // --- Modifying patterns (approval recommended) ---
    let modifying_patterns: &[(&str, &str)] = &[
        ("systemctl", "service management"),
        ("service", "service management"),
        ("docker", "container management"),
        ("podman", "container management"),
        ("chmod", "permission change"),
        ("chown", "ownership change"),
        ("mv", "file move/rename"),
        ("cp", "file copy"),
        ("sed", "in-place file edit"),
        ("tee", "file write"),
    ];

    for (pattern, reason) in modifying_patterns {
        if base_cmd == *pattern {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Modifying,
                requires_approval: true,
                reason: reason.to_string(),
                matched_pattern: Some(pattern.to_string()),
            };
        }
    }

    // AWS modifying
    if base_cmd == "aws" {
        let has_modifying = tokens.iter().any(|t| {
            matches!(*t, "update-service" | "update-function-code" | "put-item"
                | "create-stack" | "update-stack" | "run-instances"
                | "stop-instances" | "start-instances" | "scale")
        });
        if has_modifying {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Modifying,
                requires_approval: true,
                reason: "AWS resource modification".into(),
                matched_pattern: Some("aws modify".into()),
            };
        }
    }

    // kubectl modifying
    if base_cmd == "kubectl" {
        let has_modifying = tokens.iter().any(|t| {
            matches!(*t, "apply" | "patch" | "scale" | "rollout" | "edit" | "label" | "annotate")
        });
        if has_modifying {
            return Classification {
                command: trimmed.to_string(),
                safety: SafetyLevel::Modifying,
                requires_approval: true,
                reason: "Kubernetes resource modification".into(),
                matched_pattern: Some("kubectl modify".into()),
            };
        }
    }

    // --- Read-only (default) ---
    Classification {
        command: trimmed.to_string(),
        safety: SafetyLevel::ReadOnly,
        requires_approval: false,
        reason: "No destructive or modifying patterns detected".into(),
        matched_pattern: None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_read_only_commands() {
        let cases = vec!["ls -la", "cat /etc/hosts", "kubectl get pods", "aws s3 ls", "echo hello"];
        for cmd in cases {
            let result = classify(cmd);
            assert_eq!(result.safety, SafetyLevel::ReadOnly, "Expected ReadOnly for: {}", cmd);
            assert!(!result.requires_approval);
        }
    }

    #[test]
    fn test_destructive_commands() {
        let cases = vec![
            "rm -rf /tmp/data",
            "aws ec2 terminate-instances --instance-ids i-123",
            "kubectl delete pod nginx",
            "terraform destroy",
            "kill -9 1234",
            "dd if=/dev/zero of=/dev/sda",
        ];
        for cmd in cases {
            let result = classify(cmd);
            assert_eq!(result.safety, SafetyLevel::Destructive, "Expected Destructive for: {}", cmd);
            assert!(result.requires_approval);
        }
    }

    #[test]
    fn test_modifying_commands() {
        let cases = vec![
            "systemctl restart nginx",
            "docker restart my-container",
            "chmod 755 script.sh",
            "aws ecs update-service --cluster prod --service api",
            "kubectl apply -f deployment.yaml",
        ];
        for cmd in cases {
            let result = classify(cmd);
            assert_eq!(result.safety, SafetyLevel::Modifying, "Expected Modifying for: {}", cmd);
            assert!(result.requires_approval);
        }
    }

    #[test]
    fn test_empty_command() {
        let result = classify("");
        assert_eq!(result.safety, SafetyLevel::ReadOnly);
    }

    #[test]
    fn test_terraform_apply_is_destructive() {
        let result = classify("terraform apply -auto-approve");
        assert_eq!(result.safety, SafetyLevel::Destructive);
        assert!(result.requires_approval);
    }

    #[test]
    fn test_tofu_destroy_is_destructive() {
        let result = classify("tofu destroy");
        assert_eq!(result.safety, SafetyLevel::Destructive);
    }
}
