import os
import subprocess
import logging
from pathlib import Path

logger = logging.getLogger(__name__)

def generate_ssl_certs(domain: str = None, cert_dir: str = "./certs"):
    """
    Generates SSL certificates for Uvicorn.
    If domain is provided, attempts to use Certbot (requires port 80).
    Otherwise, generates a local self-signed certificate using OpenSSL.
    
    Returns (key_path, cert_path) or (None, None) if failed.
    """
    os.makedirs(cert_dir, exist_ok=True)
    key_path = os.path.join(cert_dir, "key.pem")
    cert_path = os.path.join(cert_dir, "cert.pem")
    
    # 1. Certbot Let's Encrypt path
    if domain:
        print(f"🔄 Attempting Certbot generation for domain: {domain}")
        try:
            # We use standalone mode to automatically spin up a webserver to respond to HTTP-01 challenge.
            # Requires port 80 to be unbound and forwarded.
            cmd = [
                "certbot", "certonly", "--standalone", "--non-interactive", "--agree-tos",
                "-m", f"admin@{domain}", "-d", domain,
                "--key-path", key_path, "--fullchain-path", cert_path
            ]
            
            # Since certbot usually writes to /etc/letsencrypt, we map it to output locally or symlink it.
            # However, standard certbot doesn't natively write to arbitrary dirs easily without root.
            # We'll use certbot default paths but fallback to openssl if it fails.
            result = subprocess.run(cmd, capture_output=True, text=True)
            if result.returncode == 0:
                print(f"✅ Certbot succeeded for {domain}.")
                # Default certbot paths:
                letsencrypt_path = f"/etc/letsencrypt/live/{domain}"
                if os.path.exists(letsencrypt_path):
                    return (os.path.join(letsencrypt_path, "privkey.pem"), os.path.join(letsencrypt_path, "fullchain.pem"))
            else:
                print(f"⚠️ Certbot failed: {result.stderr}. Falling back to OpenSSL Self-Signed.")
        except Exception as e:
            print(f"⚠️ Certbot exception: {e}. Falling back to OpenSSL Self-Signed.")
            
    # 2. OpenSSL Self-Signed path
    if os.path.exists(key_path) and os.path.exists(cert_path):
        return key_path, cert_path
        
    print(f"🔄 Generating Local Self-Signed Certificate via OpenSSL...")
    try:
        # Generate a 2048-bit RSA key and self-signed cert valid for 365 days
        cmd = [
            "openssl", "req", "-x509", "-newkey", "rsa:2048",
            "-keyout", key_path, "-out", cert_path,
            "-days", "365", "-nodes", "-subj", "/CN=localhost"
        ]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        if result.returncode == 0:
            print(f"✅ Self-Signed SSL generated at {cert_dir}")
            return key_path, cert_path
        else:
            print(f"❌ OpenSSL failed: {result.stderr}")
            return None, None
    except Exception as e:
        print(f"❌ OpenSSL execution failed: {e}")
        return None, None
