// Container image signature verification using Cosign
// Verifies that container images are signed and trusted

use anyhow::{Context, Result};
use std::process::Command;
use tracing::{info, warn};

pub struct ImageVerifier {
    cosign_public_key: Option<String>, // Public key for verification
}

impl ImageVerifier {
    pub fn new(cosign_public_key: Option<String>) -> Self {
        Self { cosign_public_key }
    }
    
    /// Verify a container image signature
    pub async fn verify_image(&self, image: &str, signature: Option<&str>) -> Result<bool> {
        if signature.is_none() && self.cosign_public_key.is_none() {
            warn!("No signature provided for image: {}", image);
            return Ok(false);
        }
        
        // Check if cosign is available
        let cosign_available = Command::new("cosign")
            .arg("version")
            .output()
            .is_ok();
        
        if !cosign_available {
            warn!("Cosign not available, skipping signature verification");
            return Ok(false);
        }
        
        // If public key is provided, use it for verification
        if let Some(ref public_key) = self.cosign_public_key {
            let output = Command::new("cosign")
                .arg("verify")
                .arg("--key")
                .arg(public_key)
                .arg(image)
                .output()
                .context("Failed to run cosign verify")?;
            
            if output.status.success() {
                info!("Image signature verified: {}", image);
                return Ok(true);
            } else {
                let stderr = String::from_utf8_lossy(&output.stderr);
                return Err(anyhow::anyhow!("Signature verification failed: {}", stderr));
            }
        }
        
        // If signature URL is provided, verify using that
        if let Some(sig_url) = signature {
            if sig_url.starts_with("cosign://") {
                // Extract signature reference
                let sig_ref = sig_url.strip_prefix("cosign://").unwrap();
                let output = Command::new("cosign")
                    .arg("verify")
                    .arg("--signature")
                    .arg(sig_ref)
                    .arg(image)
                    .output()
                    .context("Failed to run cosign verify")?;
                
                if output.status.success() {
                    info!("Image signature verified: {}", image);
                    return Ok(true);
                } else {
                    let stderr = String::from_utf8_lossy(&output.stderr);
                    return Err(anyhow::anyhow!("Signature verification failed: {}", stderr));
                }
            }
        }
        
        Ok(false)
    }
    
    /// Check if an image has a signature
    pub async fn has_signature(&self, image: &str) -> bool {
        // Try to find signature in registry
        let output = Command::new("cosign")
            .arg("triangulate")
            .arg(image)
            .output();
        
        output.is_ok() && output.unwrap().status.success()
    }
}
