"""
Device Management Service

Handles device activation, deactivation, and license transfers.
"""

import os
import json
import logging
from datetime import datetime, timezone, timedelta
from typing import Dict, Any, List, Optional
from pathlib import Path
import requests

from app.services.device_fingerprint import DeviceFingerprintGenerator
from app.config.config import LICENSE_SERVER_URL

logger = logging.getLogger(__name__)

# Configuration — fall back to baked-in build constant
try:
    from app.config.build_config import LICENSE_API_KEY as _BAKED_API_KEY
except ImportError:
    _BAKED_API_KEY = None

LICENSE_API_KEY = os.getenv("LICENSE_API_KEY") or _BAKED_API_KEY
CACHE_DIR = Path.home() / ".rivet"


class DeviceManager:
    """Manages device activations and license transfers"""
    
    @staticmethod
    def deactivate_current_device(license_key: str) -> Dict[str, Any]:
        """
        Detach license from current device.
        Notifies license server to free the seat, then clears local state.
        Falls back to local-only clear if server is unreachable (offline/air-gap).
        """
        try:
            fingerprint = DeviceFingerprintGenerator.generate()

            # Attempt to notify license server (best-effort)
            try:
                response = requests.post(
                    f"{LICENSE_SERVER_URL}/api/deactivate",
                    headers={"X-API-Key": LICENSE_API_KEY, "X-Product-ID": "rivet"},
                    json={"license_key": license_key, "device_fingerprint": fingerprint},
                    timeout=5
                )
                if response.status_code == 200:
                    logger.info("License seat freed on server")
                else:
                    logger.warning(f"Server deactivation returned {response.status_code}, clearing locally anyway")
            except Exception as e:
                logger.warning(f"Could not reach license server during detach (offline/air-gap): {e}")

            # Always clear local state regardless of server response
            import app.services.license_validator as lv
            DeviceManager._clear_license_cache()
            lv.LicenseValidator._update_env_file("RIVET_LICENSE_KEY", "")
            lv.LicenseValidator._update_env_file("OFFLINE_LICENSE_FILE", "")
            os.environ["RIVET_LICENSE_KEY"] = ""
            os.environ.pop("OFFLINE_LICENSE_FILE", None)
            lv.LICENSE_KEY = ""
            logger.info(f"Detach complete. LICENSE_KEY is now: '{lv.LICENSE_KEY}', cache exists: {(CACHE_DIR / 'license_cache.json').exists()}")

            return {"success": True, "message": "License detached"}
        except Exception as e:
            logger.error(f"License detach failed: {e}")
            return {"success": False, "error": f"Detach failed: {str(e)}"}
    
    @staticmethod
    def get_device_activations(license_key: str) -> Dict[str, Any]:
        """
        Get list of devices where license is activated.
        
        Args:
            license_key: License key to check
            
        Returns:
            Dict with device list and activation details
        """
        try:
            response = requests.get(
                f"{LICENSE_SERVER_URL}/api/activations",
                headers={
                    "X-API-Key": LICENSE_API_KEY,
                    "X-Product-ID": "rivet"
                },
                params={"license_key": license_key},
                timeout=10
            )
            
            if response.status_code == 200:
                data = response.json()
                return {
                    "success": True,
                    "activations": data.get("activations", []),
                    "total_seats": data.get("total_seats", 1),
                    "used_seats": data.get("used_seats", 0),
                    "available_seats": data.get("available_seats", 1)
                }
            else:
                return {
                    "success": False,
                    "error": "Failed to retrieve device activations"
                }
                
        except Exception as e:
            logger.error(f"Failed to get device activations: {e}")
            return {
                "success": False,
                "error": f"Failed to retrieve activations: {str(e)}"
            }
    
    @staticmethod
    def request_device_transfer(license_key: str, reason: str = "hardware_change") -> Dict[str, Any]:
        """
        Request automatic device transfer (for hardware changes).
        
        Args:
            license_key: License key to transfer
            reason: Reason for transfer (hardware_change, computer_replacement, etc.)
            
        Returns:
            Dict with transfer result
        """
        try:
            fingerprint = DeviceFingerprintGenerator.generate()
            metadata = DeviceFingerprintGenerator.generate_metadata()
            
            response = requests.post(
                f"{LICENSE_SERVER_URL}/api/transfer-request",
                headers={
                    "X-API-Key": LICENSE_API_KEY,
                    "X-Product-ID": "rivet"
                },
                json={
                    "license_key": license_key,
                    "new_device_fingerprint": fingerprint,
                    "new_device_name": metadata.get("hostname", "unknown"),
                    "new_device_metadata": metadata,
                    "reason": reason,
                    "requested_at": datetime.now(timezone.utc).isoformat()
                },
                timeout=10
            )
            
            if response.status_code == 200:
                result = response.json()
                if result.get("auto_approved"):
                    # Transfer was automatically approved
                    DeviceManager._clear_license_cache()
                    return {
                        "success": True,
                        "auto_approved": True,
                        "message": "License transferred to this device automatically"
                    }
                else:
                    # Transfer requires manual approval
                    return {
                        "success": True,
                        "auto_approved": False,
                        "transfer_id": result.get("transfer_id"),
                        "message": "Transfer request submitted. You'll receive an email when approved."
                    }
            else:
                error_detail = response.json().get("detail", "Transfer request failed")
                return {
                    "success": False,
                    "error": error_detail
                }
                
        except Exception as e:
            logger.error(f"Device transfer request failed: {e}")
            return {
                "success": False,
                "error": f"Transfer request failed: {str(e)}"
            }
    
    @staticmethod
    def check_hardware_similarity(license_key: str) -> Dict[str, Any]:
        """
        Check if current device is similar to previously activated device.
        Used for automatic hardware change detection.
        
        Args:
            license_key: License key to check
            
        Returns:
            Dict with similarity analysis
        """
        try:
            fingerprint = DeviceFingerprintGenerator.generate()
            metadata = DeviceFingerprintGenerator.generate_metadata()
            
            response = requests.post(
                f"{LICENSE_SERVER_URL}/api/hardware-similarity",
                headers={
                    "X-API-Key": LICENSE_API_KEY,
                    "X-Product-ID": "rivet"
                },
                json={
                    "license_key": license_key,
                    "device_fingerprint": fingerprint,
                    "device_metadata": metadata
                },
                timeout=10
            )
            
            if response.status_code == 200:
                return response.json()
            else:
                return {
                    "similar": False,
                    "confidence": 0.0,
                    "reason": "Unable to check similarity"
                }
                
        except Exception as e:
            logger.warning(f"Hardware similarity check failed: {e}")
            return {
                "similar": False,
                "confidence": 0.0,
                "reason": f"Similarity check failed: {str(e)}"
            }
    
    @staticmethod
    def _clear_license_cache():
        """Clear local license cache after deactivation"""
        try:
            cache_file = CACHE_DIR / "license_cache.json"
            if cache_file.exists():
                cache_file.unlink()
                logger.debug("License cache cleared")
        except Exception as e:
            logger.warning(f"Failed to clear license cache: {e}")
    
    @staticmethod
    def get_transfer_history(license_key: str) -> Dict[str, Any]:
        """
        Get transfer history for a license key.
        
        Args:
            license_key: License key to check
            
        Returns:
            Dict with transfer history
        """
        try:
            response = requests.get(
                f"{LICENSE_SERVER_URL}/api/transfer-history",
                headers={
                    "X-API-Key": LICENSE_API_KEY,
                    "X-Product-ID": "rivet"
                },
                params={"license_key": license_key},
                timeout=10
            )
            
            if response.status_code == 200:
                data = response.json()
                return {
                    "success": True,
                    "transfers": data.get("transfers", []),
                    "remaining_transfers": data.get("remaining_transfers", 0),
                    "annual_limit": data.get("annual_limit", 3)
                }
            else:
                return {
                    "success": False,
                    "error": "Failed to retrieve transfer history"
                }
                
        except Exception as e:
            logger.error(f"Failed to get transfer history: {e}")
            return {
                "success": False,
                "error": f"Failed to retrieve transfer history: {str(e)}"
            }
    
    @staticmethod
    def revoke_license(license_key: str, reason: str = "refund_issued") -> Dict[str, Any]:
        """
        Revoke a license (for refunds, violations, etc.).
        
        Args:
            license_key: License key to revoke
            reason: Reason for revocation
            
        Returns:
            Dict with revocation result
        """
        try:
            response = requests.post(
                f"{LICENSE_SERVER_URL}/api/revoke",
                headers={
                    "X-API-Key": LICENSE_API_KEY,
                    "X-Product-ID": "rivet"
                },
                json={
                    "license_key": license_key,
                    "reason": reason,
                    "revoked_at": datetime.now(timezone.utc).isoformat()
                },
                timeout=10
            )
            
            if response.status_code == 200:
                # Create kill switch file for immediate revocation
                DeviceManager._create_kill_switch(license_key)
                
                logger.info(f"License revoked: {license_key} (reason: {reason})")
                return {
                    "success": True,
                    "message": f"License {license_key} revoked successfully"
                }
            else:
                error_detail = response.json().get("detail", "Revocation failed")
                return {
                    "success": False,
                    "error": error_detail
                }
                
        except Exception as e:
            logger.error(f"License revocation failed: {e}")
            return {
                "success": False,
                "error": f"Revocation failed: {str(e)}"
            }
    
    @staticmethod
    def _create_kill_switch(license_key: str):
        """Create kill switch file for immediate license revocation"""
        try:
            kill_switch_file = CACHE_DIR / "license_revoked.lock"
            kill_switch_file.write_text(json.dumps({
                "license_key": license_key,
                "revoked_at": datetime.now(timezone.utc).isoformat(),
                "reason": "License revoked by administrator"
            }))
            logger.info(f"Kill switch created for license: {license_key}")
        except Exception as e:
            logger.warning(f"Failed to create kill switch: {e}")