#!/usr/bin/env python3
"""
Proxmox Review and Deployment Planning Script
Connects to both Proxmox instances, reviews configurations, checks status,
and generates a deployment plan with detailed task list.
"""

import os
import sys
import json
import requests
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from urllib.parse import urlparse

# Try to import proxmoxer, but fall back to direct API calls if not available
try:
    from proxmoxer import ProxmoxAPI
    PROXMOXER_AVAILABLE = True
except ImportError:
    PROXMOXER_AVAILABLE = False
    print("Warning: proxmoxer not installed. Using direct API calls.")
    print("Install with: pip install proxmoxer")

# Colors for terminal output
class Colors:
    RED = '\033[0;31m'
    GREEN = '\033[0;32m'
    YELLOW = '\033[1;33m'
    BLUE = '\033[0;34m'
    CYAN = '\033[0;36m'
    NC = '\033[0m'  # No Color

def log(message: str, color: str = Colors.BLUE):
    """Print a log message with timestamp."""
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print(f"{color}[{timestamp}]{Colors.NC} {message}")

def log_success(message: str):
    """Print a success message."""
    log(f"✅ {message}", Colors.GREEN)

def log_warning(message: str):
    """Print a warning message."""
    log(f"⚠️  {message}", Colors.YELLOW)

def log_error(message: str):
    """Print an error message."""
    log(f"❌ {message}", Colors.RED)

class ProxmoxClient:
    """Proxmox API client."""
    
    def __init__(self, api_url: str, username: str = None, password: str = None, 
                 token: str = None, verify_ssl: bool = True):
        self.api_url = api_url.rstrip('/')
        self.username = username
        self.password = password
        self.token = token
        self.verify_ssl = verify_ssl
        self.session = requests.Session()
        self.ticket = None
        self.csrf_token = None
        
        if not verify_ssl:
            import urllib3
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    def authenticate(self) -> bool:
        """Authenticate to Proxmox API."""
        if self.token:
            # Token authentication
            self.session.headers['Authorization'] = f'PVEAuthCookie={self.token}'
            return True
        
        if not self.username or not self.password:
            log_error("Username/password or token required")
            return False
        
        # Password authentication
        auth_url = f"{self.api_url}/api2/json/access/ticket"
        try:
            response = self.session.post(
                auth_url,
                data={'username': self.username, 'password': self.password},
                verify=self.verify_ssl,
                timeout=10
            )
            response.raise_for_status()
            data = response.json()['data']
            self.ticket = data['ticket']
            self.csrf_token = data.get('CSRFPreventionToken', '')
            self.session.headers['Cookie'] = f'PVEAuthCookie={self.ticket}'
            if self.csrf_token:
                self.session.headers['CSRFPreventionToken'] = self.csrf_token
            return True
        except Exception as e:
            log_error(f"Authentication failed: {e}")
            return False
    
    def api_call(self, endpoint: str, method: str = 'GET', data: dict = None) -> Optional[dict]:
        """Make an API call to Proxmox."""
        url = f"{self.api_url}/api2/json{endpoint}"
        try:
            if method == 'GET':
                response = self.session.get(url, verify=self.verify_ssl, timeout=10)
            elif method == 'POST':
                response = self.session.post(url, json=data, verify=self.verify_ssl, timeout=10)
            elif method == 'PUT':
                response = self.session.put(url, json=data, verify=self.verify_ssl, timeout=10)
            elif method == 'DELETE':
                response = self.session.delete(url, verify=self.verify_ssl, timeout=10)
            else:
                log_error(f"Unsupported HTTP method: {method}")
                return None
            
            response.raise_for_status()
            return response.json().get('data')
        except Exception as e:
            log_error(f"API call failed ({endpoint}): {e}")
            return None
    
    def get_version(self) -> Optional[dict]:
        """Get Proxmox version information."""
        return self.api_call('/version')
    
    def get_cluster_status(self) -> Optional[List[dict]]:
        """Get cluster status."""
        return self.api_call('/cluster/status')
    
    def get_nodes(self) -> Optional[List[dict]]:
        """Get list of nodes."""
        return self.api_call('/nodes')
    
    def get_node_status(self, node: str) -> Optional[dict]:
        """Get status of a specific node."""
        return self.api_call(f'/nodes/{node}/status')
    
    def get_storage(self) -> Optional[List[dict]]:
        """Get storage information."""
        return self.api_call('/storage')
    
    def get_vms(self, node: str) -> Optional[List[dict]]:
        """Get VMs on a node."""
        return self.api_call(f'/nodes/{node}/qemu')
    
    def get_networks(self, node: str) -> Optional[List[dict]]:
        """Get network configuration for a node."""
        return self.api_call(f'/nodes/{node}/network')

def load_environment():
    """Load environment variables."""
    env_file = Path(__file__).parent.parent / '.env'
    env_vars = {}
    
    if env_file.exists():
        with open(env_file) as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith('#') and '=' in line:
                    key, value = line.split('=', 1)
                    env_vars[key.strip()] = value.strip()
    
    # Set defaults
    config = {
        'proxmox_1': {
            'api_url': env_vars.get('PROXMOX_1_API_URL', 'https://192.168.11.10:8006'),
            'user': env_vars.get('PROXMOX_1_USER', 'root'),
            'password': env_vars.get('PROXMOX_1_PASS', ''),
            'token': env_vars.get('PROXMOX_1_API_TOKEN', ''),
            'verify_ssl': env_vars.get('PROXMOX_1_INSECURE_SKIP_TLS_VERIFY', 'false').lower() != 'true'
        },
        'proxmox_2': {
            'api_url': env_vars.get('PROXMOX_2_API_URL', 'https://192.168.11.11:8006'),
            'user': env_vars.get('PROXMOX_2_USER', 'root'),
            'password': env_vars.get('PROXMOX_2_PASS', ''),
            'token': env_vars.get('PROXMOX_2_API_TOKEN', ''),
            'verify_ssl': env_vars.get('PROXMOX_2_INSECURE_SKIP_TLS_VERIFY', 'false').lower() != 'true'
        }
    }
    
    return config

def connect_and_review(client: ProxmoxClient, instance_num: int, output_dir: Path) -> Optional[dict]:
    """Connect to Proxmox and gather information."""
    log(f"Connecting to Proxmox Instance {instance_num}...")
    
    if not client.authenticate():
        log_error(f"Failed to authenticate to Instance {instance_num}")
        return None
    
    log_success(f"Authenticated to Instance {instance_num}")
    
    # Gather information
    info = {
        'instance': instance_num,
        'timestamp': datetime.now().isoformat(),
        'version': client.get_version(),
        'cluster_status': client.get_cluster_status(),
        'nodes': client.get_nodes(),
        'storage': client.get_storage()
    }
    
    # Get detailed node information
    if info['nodes']:
        log(f"  Found {len(info['nodes'])} nodes")
        for node_data in info['nodes']:
            node = node_data.get('node', 'unknown')
            log(f"    - {node}")
            
            # Get node status
            node_status = client.get_node_status(node)
            if node_status:
                info[f'node_{node}_status'] = node_status
            
            # Get VMs
            vms = client.get_vms(node)
            if vms:
                info[f'node_{node}_vms'] = vms
                log(f"      VMs: {len(vms)}")
            
            # Get networks
            networks = client.get_networks(node)
            if networks:
                info[f'node_{node}_networks'] = networks
    
    # Save to file
    output_file = output_dir / f"proxmox-{instance_num}-status-{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
    with open(output_file, 'w') as f:
        json.dump(info, f, indent=2)
    
    log_success(f"Status saved to {output_file}")
    
    # Display summary
    if info.get('version'):
        version = info['version'].get('version', 'unknown')
        log(f"  Version: {version}")
    
    return info

def review_configurations(project_root: Path, output_dir: Path) -> str:
    """Review and document configurations."""
    log("Reviewing configurations...")
    
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    config_file = output_dir / f"configuration-review-{timestamp}.md"
    
    content = []
    content.append("# Proxmox Configuration Review\n")
    content.append(f"Generated: {datetime.now().isoformat()}\n")
    
    # Environment configuration
    content.append("## Environment Configuration\n")
    content.append("### Proxmox Instance 1\n")
    content.append("- API URL: From .env (PROXMOX_1_API_URL)\n")
    content.append("- User: From .env (PROXMOX_1_USER)\n")
    content.append("\n### Proxmox Instance 2\n")
    content.append("- API URL: From .env (PROXMOX_2_API_URL)\n")
    content.append("- User: From .env (PROXMOX_2_USER)\n")
    content.append("\n")
    
    # Provider config
    provider_config = project_root / "crossplane-provider-proxmox" / "examples" / "provider-config.yaml"
    if provider_config.exists():
        content.append("## Crossplane Provider Configuration\n")
        content.append("```yaml\n")
        with open(provider_config) as f:
            content.append(f.read())
        content.append("```\n\n")
    
    # Cloudflare tunnel configs
    tunnel_configs_dir = project_root / "cloudflare" / "tunnel-configs"
    if tunnel_configs_dir.exists():
        content.append("## Cloudflare Tunnel Configurations\n")
        for config_file in sorted(tunnel_configs_dir.glob("proxmox-site-*.yaml")):
            content.append(f"### {config_file.name}\n")
            content.append("```yaml\n")
            with open(config_file) as f:
                content.append(f.read())
            content.append("```\n\n")
    
    with open(config_file, 'w') as f:
        f.write(''.join(content))
    
    log_success(f"Configuration review saved to {config_file}")
    return str(config_file)

def generate_deployment_plan(output_dir: Path, config: dict) -> str:
    """Generate deployment plan."""
    log("Generating deployment plan...")
    
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    plan_file = output_dir / f"deployment-plan-{timestamp}.md"
    
    content = []
    content.append("# Proxmox Deployment Plan\n")
    content.append(f"Generated: {datetime.now().isoformat()}\n")
    content.append("## Current Status\n")
    content.append(f"- **Instance 1**: {config['proxmox_1']['api_url']}\n")
    content.append(f"- **Instance 2**: {config['proxmox_2']['api_url']}\n")
    content.append("\n## Deployment Phases\n")
    content.append("### Phase 1: Connection and Validation\n")
    content.append("1. Verify connectivity to both instances\n")
    content.append("2. Review cluster status and node health\n")
    content.append("3. Review storage and network configuration\n")
    content.append("\n### Phase 2: Configuration Alignment\n")
    content.append("1. Map instances to sites\n")
    content.append("2. Set up authentication (API tokens)\n")
    content.append("3. Configure Cloudflare tunnels\n")
    content.append("\n### Phase 3: Crossplane Provider Deployment\n")
    content.append("1. Complete API client implementation\n")
    content.append("2. Build and deploy provider\n")
    content.append("3. Configure ProviderConfig\n")
    content.append("\n### Phase 4: Infrastructure Deployment\n")
    content.append("1. Deploy test VMs\n")
    content.append("2. Set up monitoring\n")
    content.append("3. Configure backups\n")
    content.append("\n### Phase 5: Production Readiness\n")
    content.append("1. Security hardening\n")
    content.append("2. Documentation\n")
    content.append("3. Testing and validation\n")
    
    with open(plan_file, 'w') as f:
        f.write(''.join(content))
    
    log_success(f"Deployment plan saved to {plan_file}")
    return str(plan_file)

def generate_task_list(output_dir: Path, config: dict) -> str:
    """Generate detailed task list."""
    log("Generating task list...")
    
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    task_file = output_dir / f"task-list-{timestamp}.md"
    
    content = []
    content.append("# Proxmox Deployment Task List\n")
    content.append(f"Generated: {datetime.now().isoformat()}\n")
    content.append("## Immediate Tasks (Priority: High)\n")
    content.append("### Connection and Authentication\n")
    content.append("- [ ] **TASK-001**: Verify connectivity to Instance 1\n")
    content.append(f"  - URL: {config['proxmox_1']['api_url']}\n")
    content.append("- [ ] **TASK-002**: Verify connectivity to Instance 2\n")
    content.append(f"  - URL: {config['proxmox_2']['api_url']}\n")
    content.append("- [ ] **TASK-003**: Test authentication to Instance 1\n")
    content.append("- [ ] **TASK-004**: Test authentication to Instance 2\n")
    content.append("\n### Configuration Review\n")
    content.append("- [ ] **TASK-005**: Review provider-config.yaml\n")
    content.append("- [ ] **TASK-006**: Review Cloudflare tunnel configs\n")
    content.append("- [ ] **TASK-007**: Map instances to sites\n")
    content.append("\n## Short-term Tasks (Priority: Medium)\n")
    content.append("### Crossplane Provider\n")
    content.append("- [ ] **TASK-008**: Complete Proxmox API client implementation\n")
    content.append("- [ ] **TASK-009**: Build and test provider\n")
    content.append("- [ ] **TASK-010**: Deploy provider to Kubernetes\n")
    content.append("- [ ] **TASK-011**: Create ProviderConfig resource\n")
    content.append("\n### Infrastructure Setup\n")
    content.append("- [ ] **TASK-012**: Deploy Prometheus exporters\n")
    content.append("- [ ] **TASK-013**: Configure Cloudflare tunnels\n")
    content.append("- [ ] **TASK-014**: Set up monitoring dashboards\n")
    content.append("\n## Long-term Tasks (Priority: Low)\n")
    content.append("- [ ] **TASK-015**: Deploy test VMs\n")
    content.append("- [ ] **TASK-016**: End-to-end testing\n")
    content.append("- [ ] **TASK-017**: Performance testing\n")
    content.append("- [ ] **TASK-018**: Create runbooks\n")
    content.append("- [ ] **TASK-019**: Set up backups\n")
    content.append("- [ ] **TASK-020**: Security audit\n")
    
    with open(task_file, 'w') as f:
        f.write(''.join(content))
    
    log_success(f"Task list saved to {task_file}")
    return str(task_file)

def main():
    """Main execution."""
    log("Starting Proxmox Review and Deployment Planning...")
    log("=" * 50)
    
    project_root = Path(__file__).parent.parent
    output_dir = project_root / "docs" / "proxmox-review"
    output_dir.mkdir(parents=True, exist_ok=True)
    
    config = load_environment()
    
    log("\n=== Phase 1: Connecting to Proxmox Instances ===")
    
    # Connect to Instance 1
    client1 = ProxmoxClient(
        config['proxmox_1']['api_url'],
        config['proxmox_1']['user'],
        config['proxmox_1']['password'],
        config['proxmox_1']['token'],
        config['proxmox_1']['verify_ssl']
    )
    info1 = connect_and_review(client1, 1, output_dir)
    
    log("")
    
    # Connect to Instance 2
    client2 = ProxmoxClient(
        config['proxmox_2']['api_url'],
        config['proxmox_2']['user'],
        config['proxmox_2']['password'],
        config['proxmox_2']['token'],
        config['proxmox_2']['verify_ssl']
    )
    info2 = connect_and_review(client2, 2, output_dir)
    
    log("\n=== Phase 2: Reviewing Configurations ===")
    review_configurations(project_root, output_dir)
    
    log("\n=== Phase 3: Generating Deployment Plan ===")
    generate_deployment_plan(output_dir, config)
    
    log("\n=== Phase 4: Generating Task List ===")
    generate_task_list(output_dir, config)
    
    log("\n" + "=" * 50)
    log_success("Review and planning completed!")
    log(f"\nOutput directory: {output_dir}")

if __name__ == '__main__':
    main()

