#!/usr/bin/env python3
"""
Unraid VM Manager for ThrillWiki - Template-Based Main Orchestrator
Uses pre-built template VMs for fast deployment instead of autoinstall.
"""

import os
import sys
import logging
from pathlib import Path

# Import our modular components
from template_manager import TemplateVMManager
from vm_manager_template import UnraidTemplateVMManager


class ConfigLoader:
    """Dynamic configuration loader that reads environment variables when needed."""

    def __init__(self):
        # Try to load ***REMOVED***.unraid if it exists to ensure we have the
        # latest config
        self._load_env_file()

    def _load_env_file(self):
        """Load ***REMOVED***.unraid file if it exists."""
        # Find the project directory (two levels up from this script)
        script_dir = Path(__file__).parent
        project_dir = script_dir.parent.parent
        env_file = project_dir / "***REMOVED***.unraid"

        if env_file.exists():
            try:
                with open(env_file, "r") as f:
                    for line in f:
                        line = line.strip()
                        if line and not line.startswith("#") and "=" in line:
                            key, value = line.split("=", 1)
                            # Remove quotes if present
                            value = value.strip("\"'")
                            # Only set if not already in environment (env vars
                            # take precedence)
                            if key not in os.environ:
                                os.environ[key] = value

                logging.info(f"📝 Loaded configuration from {env_file}")
            except Exception as e:
                logging.warning(f"⚠️  Could not load ***REMOVED***.unraid: {e}")

    @property
    def UNRAID_HOST(self):
        return os.environ.get("UNRAID_HOST", "localhost")

    @property
    def UNRAID_USER(self):
        return os.environ.get("UNRAID_USER", "root")

    @property
    def VM_NAME(self):
        return os.environ.get("VM_NAME", "thrillwiki-vm")

    @property
    def VM_MEMORY(self):
        return int(os.environ.get("VM_MEMORY", 4096))

    @property
    def VM_VCPUS(self):
        return int(os.environ.get("VM_VCPUS", 2))

    @property
    def VM_DISK_SIZE(self):
        return int(os.environ.get("VM_DISK_SIZE", 50))

    @property
    def SSH_PUBLIC_KEY(self):
        return os.environ.get("SSH_PUBLIC_KEY", "")

    @property
    def VM_IP(self):
        return os.environ.get("VM_IP", "dhcp")

    @property
    def VM_GATEWAY(self):
        return os.environ.get("VM_GATEWAY", "192.168.20.1")

    @property
    def VM_NETMASK(self):
        return os.environ.get("VM_NETMASK", "255.255.255.0")

    @property
    def VM_NETWORK(self):
        return os.environ.get("VM_NETWORK", "192.168.20.0/24")

    @property
    def REPO_URL(self):
        return os.environ.get("REPO_URL", "")

    @property
    def GITHUB_USERNAME(self):
        return os.environ.get("GITHUB_USERNAME", "")

    @property
    def GITHUB_TOKEN(self):
        return os.environ.get("GITHUB_TOKEN", "")


# Create a global configuration instance
config = ConfigLoader()

# Setup logging with reduced buffering
os.makedirs("logs", exist_ok=True)

# Configure console handler with line buffering
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(
    logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
)
# Force flush after each log message
console_handler.flush = lambda: sys.stdout.flush()

# Configure file handler
file_handler = logging.FileHandler("logs/unraid-vm.log")
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(
    logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
)

# Set up basic config with both handlers
logging.basicConfig(
    level=logging.INFO,
    handlers=[file_handler, console_handler],
)

# Ensure stdout is line buffered for real-time output
sys.stdout.reconfigure(line_buffering=True)
logger = logging.getLogger(__name__)


class ThrillWikiTemplateVMOrchestrator:
    """Main orchestrator for template-based ThrillWiki VM deployment."""

    def __init__(self):
        # Log current configuration for debugging
        logger.info(
            f"🔧 Using configuration: UNRAID_HOST={
                config.UNRAID_HOST}, UNRAID_USER={
                config.UNRAID_USER}, VM_NAME={
                config.VM_NAME}"
        )

        self.template_manager = TemplateVMManager(
            config.UNRAID_HOST, config.UNRAID_USER
        )
        self.vm_manager = UnraidTemplateVMManager(
            config.VM_NAME, config.UNRAID_HOST, config.UNRAID_USER
        )

    def check_template_ready(self) -> bool:
        """Check if template VM is ready for use."""
        logger.info("🔍 Checking template VM availability...")

        if not self.template_manager.check_template_exists():
            logger.error("❌ Template VM disk not found!")
            logger.error(
                "Please ensure 'thrillwiki-template-ubuntu' VM exists and is properly configured"
            )
            logger.error(
                "Template should be located at: /mnt/user/domains/thrillwiki-template-ubuntu/vdisk1.qcow2"
            )
            return False

        # Check template status
        if not self.template_manager.update_template():
            logger.warning("⚠️  Template VM may be running - this could cause issues")
            logger.warning(
                "Ensure the template VM is stopped before creating new instances"
            )

        info = self.template_manager.get_template_info()
        if info:
            logger.info(f"📋 Template Info:")
            logger.info(f"   Virtual Size: {info['virtual_size']}")
            logger.info(f"   File Size: {info['file_size']}")
            logger.info(f"   Last Modified: {info['last_modified']}")

        return True

    def deploy_vm_from_template(self) -> bool:
        """Complete template-based VM deployment process."""
        try:
            logger.info("🚀 Starting ThrillWiki template-based VM deployment...")

            # Step 1: Check SSH connectivity
            logger.info("📡 Testing Unraid connectivity...")
            if not self.vm_manager.authenticate():
                logger.error("❌ Cannot connect to Unraid server")
                return False

            # Step 2: Check template availability
            logger.info("🔍 Verifying template VM...")
            if not self.check_template_ready():
                logger.error("❌ Template VM not ready")
                return False

            # Step 3: Create VM from template
            logger.info("⚙️  Creating VM from template...")
            success = self.vm_manager.create_vm_from_template(
                vm_memory=config.VM_MEMORY,
                vm_vcpus=config.VM_VCPUS,
                vm_disk_size=config.VM_DISK_SIZE,
                vm_ip=config.VM_IP,
            )

            if not success:
                logger.error("❌ Failed to create VM from template")
                return False

            # Step 4: Start VM
            logger.info("🟢 Starting VM...")
            success = self.vm_manager.start_vm()

            if not success:
                logger.error("❌ Failed to start VM")
                return False

            logger.info("🎉 Template-based VM deployment completed successfully!")
            logger.info("")
            logger.info("📋 Next Steps:")
            logger.info("1. VM is now booting from template disk")
            logger.info("2. Boot time should be much faster (2-5 minutes)")
            logger.info("3. Use 'python main_template.py ip' to get VM IP when ready")
            logger.info("4. SSH to VM and run deployment commands")
            logger.info("")

            return True

        except Exception as e:
            logger.error(f"❌ Template VM deployment failed: {e}")
            return False

    def deploy_and_configure_thrillwiki(self) -> bool:
        """Deploy VM from template and configure ThrillWiki."""
        try:
            logger.info("🚀 Starting complete ThrillWiki deployment from template...")

            # Step 1: Deploy VM from template
            if not self.deploy_vm_from_template():
                return False

            # Step 2: Wait for VM to be accessible and configure ThrillWiki
            if config.REPO_URL:
                logger.info("🔧 Configuring ThrillWiki on VM...")
                success = self.vm_manager.customize_vm_for_thrillwiki(
                    config.REPO_URL, config.GITHUB_TOKEN
                )

                if success:
                    vm_ip = self.vm_manager.get_vm_ip()
                    logger.info("🎉 Complete ThrillWiki deployment successful!")
                    logger.info(f"🌐 ThrillWiki is available at: http://{vm_ip}:8000")
                else:
                    logger.warning(
                        "⚠️  VM deployed but ThrillWiki configuration may have failed"
                    )
                    logger.info(
                        "You can manually configure ThrillWiki by SSH'ing to the VM"
                    )
            else:
                logger.info(
                    "📝 No repository URL provided - VM deployed but ThrillWiki not configured"
                )
                logger.info(
                    "Set REPO_URL environment variable to auto-configure ThrillWiki"
                )

            return True

        except Exception as e:
            logger.error(f"❌ Complete deployment failed: {e}")
            return False

    def get_vm_info(self) -> dict:
        """Get VM information."""
        return {
            "name": config.VM_NAME,
            "status": self.vm_manager.vm_status(),
            "ip": self.vm_manager.get_vm_ip(),
            "memory": config.VM_MEMORY,
            "vcpus": config.VM_VCPUS,
            "disk_size": config.VM_DISK_SIZE,
            "deployment_type": "template-based",
        }


def main():
    """Main entry point."""
    import argparse

    parser = argparse.ArgumentParser(
        description="ThrillWiki Template-Based VM Manager - Fast VM deployment using templates",
        epilog="""
Examples:
  python main_template.py setup        # Deploy VM from template only
  python main_template.py deploy       # Deploy VM and configure ThrillWiki
  python main_template.py start        # Start existing VM
  python main_template.py ip           # Get VM IP address
  python main_template.py status       # Get VM status
  python main_template.py delete       # Remove VM completely
  python main_template.py template     # Manage template VM
        """,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )

    parser.add_argument(
        "action",
        choices=[
            "setup",
            "deploy",
            "create",
            "start",
            "stop",
            "status",
            "ip",
            "delete",
            "info",
            "template",
        ],
        help="Action to perform",
    )

    parser.add_argument(
        "template_action",
        nargs="?",
        choices=["info", "check", "update", "list"],
        help="Template management action (used with 'template' action)",
    )

    args = parser.parse_args()

    # Create orchestrator
    orchestrator = ThrillWikiTemplateVMOrchestrator()

    if args.action == "setup":
        logger.info("🚀 Setting up VM from template...")
        success = orchestrator.deploy_vm_from_template()
        sys.exit(0 if success else 1)

    elif args.action == "deploy":
        logger.info("🚀 Complete ThrillWiki deployment from template...")
        success = orchestrator.deploy_and_configure_thrillwiki()
        sys.exit(0 if success else 1)

    elif args.action == "create":
        logger.info("⚙️  Creating VM from template...")
        success = orchestrator.vm_manager.create_vm_from_template(
            config.VM_MEMORY,
            config.VM_VCPUS,
            config.VM_DISK_SIZE,
            config.VM_IP,
        )
        sys.exit(0 if success else 1)

    elif args.action == "start":
        logger.info("🟢 Starting VM...")
        success = orchestrator.vm_manager.start_vm()
        sys.exit(0 if success else 1)

    elif args.action == "stop":
        logger.info("🛑 Stopping VM...")
        success = orchestrator.vm_manager.stop_vm()
        sys.exit(0 if success else 1)

    elif args.action == "status":
        status = orchestrator.vm_manager.vm_status()
        print(f"VM Status: {status}")
        sys.exit(0)

    elif args.action == "ip":
        ip = orchestrator.vm_manager.get_vm_ip()
        if ip:
            print(f"VM IP: {ip}")
            print(f"SSH: ssh thrillwiki@{ip}")
            print(f"ThrillWiki: http://{ip}:8000")
            sys.exit(0)
        else:
            print("❌ Failed to get VM IP (VM may not be ready yet)")
            sys.exit(1)

    elif args.action == "info":
        info = orchestrator.get_vm_info()
        print("🖥️  VM Information:")
        print(f"   Name: {info['name']}")
        print(f"   Status: {info['status']}")
        print(f"   IP: {info['ip'] or 'Not available'}")
        print(f"   Memory: {info['memory']} MB")
        print(f"   vCPUs: {info['vcpus']}")
        print(f"   Disk: {info['disk_size']} GB")
        print(f"   Type: {info['deployment_type']}")
        sys.exit(0)

    elif args.action == "delete":
        logger.info("🗑️  Deleting VM and all files...")
        success = orchestrator.vm_manager.delete_vm()
        sys.exit(0 if success else 1)

    elif args.action == "template":
        template_action = args.template_action or "info"

        if template_action == "info":
            logger.info("📋 Template VM Information")
            info = orchestrator.template_manager.get_template_info()
            if info:
                print(f"Template Path: {info['template_path']}")
                print(f"Virtual Size: {info['virtual_size']}")
                print(f"File Size: {info['file_size']}")
                print(f"Last Modified: {info['last_modified']}")
            else:
                print("❌ Failed to get template information")
                sys.exit(1)

        elif template_action == "check":
            if orchestrator.template_manager.check_template_exists():
                logger.info("✅ Template VM disk exists and is ready to use")
                sys.exit(0)
            else:
                logger.error("❌ Template VM disk not found")
                sys.exit(1)

        elif template_action == "update":
            success = orchestrator.template_manager.update_template()
            sys.exit(0 if success else 1)

        elif template_action == "list":
            logger.info("📋 Template-based VM Instances")
            instances = orchestrator.template_manager.list_template_instances()
            if instances:
                for instance in instances:
                    status_emoji = (
                        "🟢"
                        if instance["status"] == "running"
                        else "🔴" if instance["status"] == "shut off" else "🟡"
                    )
                    print(
                        f"{status_emoji} {
                            instance['name']} ({
                            instance['status']})"
                    )
            else:
                print("No template instances found")

        sys.exit(0)


if __name__ == "__main__":
    main()
