#!/usr/bin/env python3
"""
Simulation script for VeriFactu API certificate validation.
Simulates a real user making API calls to register certificates.
"""

# ==================== CONFIGURABLE PASSWORD ====================
# THIS MUST MATCH THE PASSWORD IN generate_certs.py
CERT_PASSWORD = "Mecedora12@"

# RUTA DEL CERTIFICADO REAL
REAL_CERT_PATH = r"D:\Importante\53950250R_JOSEP VICENT_MESTRE__1752317947215 - copia.p12"
# ============================================================

import os
import sys
import base64
import json
import datetime
import subprocess
from pathlib import Path
from urllib.request import urlopen, Request
from urllib.error import URLError

API_URL = "http://localhost:6789"
CERTS_DIR = Path(__file__).parent / "certs"

# Try to import cryptography for RSA encryption
try:
    from cryptography import x509
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives.asymmetric import padding
    from cryptography.hazmat.backends import default_backend
    HAS_CRYPTO = True
except ImportError:
    HAS_CRYPTO = False


def call_api(endpoint, data=None, method="GET"):
    """Make HTTP call to API."""
    url = f"{API_URL}{endpoint}"
    
    try:
        if method == "GET":
            req = Request(url, method="GET")
        else:
            req = Request(url, data=json.dumps(data).encode(), method="POST")
            req.add_header("Content-Type", "application/json")
        
        with urlopen(req, timeout=10) as response:
            return json.loads(response.read().decode())
    except URLError as e:
        return {"error": str(e)}
    except Exception as e:
        return {"error": f"API call failed: {e}"}


def get_public_key():
    """Step 1: Get public key from API."""
    print("\n" + "=" * 60)
    print("STEP 1: Get Public Key from API")
    print("=" * 60)
    
    result = call_api("/api/v1/health")
    print(f"Health check: {result}")
    
    if "error" in result:
        print(f"ERROR: API not running - {result}")
        return None
    
    result = call_api("/api/v1/auth/public-key")
    
    if "public_key" not in result:
        print(f"ERROR: No public key in response")
        return None
    
    pub_key_b64 = result["public_key"]
    pub_key = base64.b64decode(pub_key_b64)
    
    print(f"Public Key received (length: {len(pub_key)} bytes)")
    return pub_key


def encrypt_password(public_key_pem, password):
    """Step 2: Encrypt password with public key (RSA)."""
    print("\n" + "=" * 60)
    print("STEP 2: Encrypt Password")
    print("=" * 60)
    
    if not HAS_CRYPTO:
        print("WARNING: cryptography not available, using base64 (NOT SECURE!)")
        return base64.b64encode(password.encode()).decode()
    
    try:
        public_key = serialization.load_pem_public_key(public_key_pem, default_backend())
        
        encrypted = public_key.encrypt(
            password.encode(),
            padding.PKCS1v15()
        )
        
        encrypted_b64 = base64.b64encode(encrypted).decode()
        print(f"Password encrypted (RSA)")
        return encrypted_b64
        
    except Exception as e:
        print(f"ERROR encrypting: {e}")
        return None


def register_certificate(cert_path, encrypted_password, test_name="default"):
    """Step 3: Register certificate via API."""
    print("\n" + "=" * 60)
    print("STEP 3: Register Certificate")
    print("=" * 60)
    print(f"Certificate path: {cert_path}")
    print(f"Password (encrypted): {encrypted_password[:40]}...")
    
    data = {
        "cert_name": test_name.replace(" ", "_").replace("(", "").replace(")", ""),
        "cert_path": cert_path,
        "password_encrypted": encrypted_password
    }
    
    result = call_api("/api/v1/auth/register", data, method="POST")
    
    return result


def test_certificate(cert_file, password, expected_result, test_name):
    """Test a single certificate via real API calls."""
    print(f"\n{'#' * 60}")
    print(f"# TEST: {test_name}")
    print(f"# Expected: {expected_result}")
    print(f"{'#' * 60}")
    
    # Step 1: Get public key
    pub_key = get_public_key()
    if not pub_key:
        print("[X] Cannot get public key - is API running?")
        return
    
    # Step 2: Encrypt password
    enc_password = encrypt_password(pub_key, password)
    if not enc_password:
        print("[X] Cannot encrypt password")
        return
    
    # Step 3: Register certificate
    cert_path = str(CERTS_DIR / cert_file)
    result = register_certificate(cert_path, enc_password, test_name)
    
    print(f"\nAPI Response:")
    print(json.dumps(result, indent=2))
    
    # Validate result
    success = result.get("success", False)
    error = result.get("error", "")
    warnings = result.get("warnings", [])
    
    if expected_result == "PASS" and success:
        print(f"\n[OK] TEST PASSED")
    elif expected_result == "FAIL" and not success:
        print(f"\n[OK] TEST PASSED (expected failure: {error})")
    elif expected_result == "PASS with WARNING" and success and warnings:
        print(f"\n[OK] TEST PASSED (with warnings: {warnings})")
    else:
        print(f"\n[FAIL] TEST FAILED (success={success}, error={error})")


def main():
    """Main test runner."""
    print("=" * 60)
    print("VeriFactu API - Real User Simulation")
    print("=" * 60)
    print(f"\nAPI URL: {API_URL}")
    print(f"Certs Directory: {CERTS_DIR}")
    
    # Check if API is running
    print("\nChecking if API is running...")
    result = call_api("/api/v1/health")
    if "error" in result:
        print("ERROR: API not running!")
        print("Start with: ./verifactu.exe")
        return
    
    print(f"API is running!")
    
    print("\n" + "=" * 60)
    print("Running Tests via Real API Calls")
    print("=" * 60)
    
    test_cases = [
        ("valid_365days.p12", CERT_PASSWORD, "PASS", "Valid certificate (365 days)"),
        ("valid_60days.p12", CERT_PASSWORD, "PASS", "Valid certificate (60 days)"),
        ("expired.p12", CERT_PASSWORD, "FAIL", "Expired certificate"),
        ("expiring_soon.p12", CERT_PASSWORD, "PASS with WARNING", "Expiring soon (15 days)"),
        ("not_yet_valid.p12", CERT_PASSWORD, "FAIL", "Not yet valid certificate"),
        ("wrong_password.p12", CERT_PASSWORD, "FAIL", "Wrong password"),
        (REAL_CERT_PATH, CERT_PASSWORD, "PASS", "REAL certificate with REAL password"),
    ]
    
    for cert_file, password, expected, test_name in test_cases:
        test_certificate(cert_file, password, expected, test_name)
    
    print("\n" + "=" * 60)
    print("ALL TESTS COMPLETED")
    print("=" * 60)


if __name__ == "__main__":
    main()