"""
Licensing system for DataShaper AI - Free vs Pro tiers.
"""

import os
import json
import hashlib
import base64
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional, Dict, Any
from dataclasses import dataclass
from enum import Enum


class Tier(Enum):
    """User tier levels."""
    FREE = "free"
    PRO = "pro"


@dataclass
class License:
    """License information."""
    tier: Tier
    email: str
    expires_at: Optional[datetime] = None
    features: Dict[str, bool] = None
    
    def is_valid(self) -> bool:
        """Check if license is still valid."""
        if self.tier == Tier.FREE:
            return True
        
        if self.expires_at is None:
            return True  # Lifetime license
        
        return datetime.now() < self.expires_at
    
    def is_pro(self) -> bool:
        """Check if user has pro tier."""
        return self.tier == Tier.PRO and self.is_valid()


class LicenseManager:
    """Manages license validation and tier features."""
    
    # Free tier limits
    FREE_MAX_FILE_SIZE_MB = 25
    
    # Pro features
    PRO_FEATURES = {
        'unlimited_file_size': True,
        'zip_download': True,
        'schema_export': True,
        'flag_only_mode': True,
        'remove_branding': True,
        'priority_support': True,
        'rule_packs': True,
        'future_features': True,
    }
    
    def __init__(self, license_path: Optional[Path] = None):
        """Initialize license manager."""
        if license_path is None:
            license_path = Path.home() / '.datashaper' / 'license.json'
        
        self.license_path = license_path
        self.license_path.parent.mkdir(parents=True, exist_ok=True)
        self._license: Optional[License] = None
        self._load_license()
    
    def _load_license(self):
        """Load license from disk."""
        if not self.license_path.exists():
            # Default to free tier
            self._license = License(
                tier=Tier.FREE,
                email="free@user.com",
                features={}
            )
            return
        
        try:
            with open(self.license_path, 'r') as f:
                data = json.load(f)
            
            expires_at = None
            if data.get('expires_at'):
                expires_at = datetime.fromisoformat(data['expires_at'])
            
            self._license = License(
                tier=Tier(data.get('tier', 'free')),
                email=data.get('email', 'free@user.com'),
                expires_at=expires_at,
                features=data.get('features', {})
            )
        except Exception as e:
            # If any error, default to free
            self._license = License(
                tier=Tier.FREE,
                email="free@user.com",
                features={}
            )
    
    def save_license(self, license: License):
        """Save license to disk."""
        data = {
            'tier': license.tier.value,
            'email': license.email,
            'expires_at': license.expires_at.isoformat() if license.expires_at else None,
            'features': license.features or {}
        }
        
        with open(self.license_path, 'w') as f:
            json.dump(data, f, indent=2)
        
        self._license = license
    
    def activate_license(self, license_key: str) -> bool:
        """
        Activate a license key.
        
        Format: BASE64(email|tier|expiry_date|signature)
        """
        try:
            decoded = base64.b64decode(license_key).decode('utf-8')
            parts = decoded.split('|')
            
            if len(parts) < 4:
                return False
            
            email = parts[0]
            tier = parts[1]
            expiry = parts[2]
            signature = parts[3]
            
            # Verify signature (simple HMAC-like check)
            expected_sig = self._generate_signature(email, tier, expiry)
            if signature != expected_sig:
                return False
            
            # Parse expiry
            expires_at = None
            if expiry != 'lifetime':
                expires_at = datetime.fromisoformat(expiry)
            
            # Create license
            license = License(
                tier=Tier(tier),
                email=email,
                expires_at=expires_at,
                features=self.PRO_FEATURES if tier == 'pro' else {}
            )
            
            self.save_license(license)
            return True
            
        except Exception:
            return False
    
    def _generate_signature(self, email: str, tier: str, expiry: str) -> str:
        """Generate signature for license validation."""
        secret = os.getenv("LICENSE_SECRET_KEY", "datashaper-ai-2024")
        data = f"{email}|{tier}|{expiry}|{secret}"
        return hashlib.sha256(data.encode()).hexdigest()[:16]
    
    def get_tier(self) -> Tier:
        """Get current user tier."""
        if self._license and self._license.is_valid():
            return self._license.tier
        return Tier.FREE
    
    def is_pro(self) -> bool:
        """Check if user has valid pro license."""
        return self._license.is_pro() if self._license else False
    
    def can_use_feature(self, feature: str) -> bool:
        """Check if user can access a feature."""
        if self.is_pro():
            return True
        
        # Free tier features
        free_features = [
            'basic_cleaning',
            'html_reports',
            'unlimited_files',
            'batch_processing'
        ]
        
        return feature in free_features
    
    def get_max_file_size_mb(self) -> Optional[int]:
        """Get maximum file size limit in MB (None = unlimited)."""
        if self.is_pro():
            return None  # Unlimited
        return self.FREE_MAX_FILE_SIZE_MB
    
    def get_feature_limits(self) -> Dict[str, Any]:
        """Get all feature limits for current tier."""
        is_pro = self.is_pro()
        
        return {
            'tier': self.get_tier().value,
            'max_file_size_mb': None if is_pro else self.FREE_MAX_FILE_SIZE_MB,
            'unlimited_files': True,  # Both tiers
            'zip_download': is_pro,
            'schema_export': is_pro,
            'flag_only_mode': is_pro,
            'remove_branding': is_pro,
            'priority_support': is_pro,
            'rule_packs': is_pro,
        }
    
    def get_upgrade_message(self) -> str:
        """Get upgrade message for free users."""
        return """
🚀 Upgrade to PRO for:
• Unlimited file size
• One-click ZIP download
• Schema.json export
• Flag-only mode
• Remove branding
• Priority support + rule packs
• All future features FREE

₹149/month (₹999/year) — India
$9/month ($79/year) — International
        """.strip()


def generate_license_key(email: str, tier: str, expiry: Optional[datetime] = None) -> str:
    """
    Generate a license key (admin utility).
    
    Args:
        email: User email
        tier: 'free' or 'pro'
        expiry: Expiry date (None for lifetime)
    """
    expiry_str = 'lifetime' if expiry is None else expiry.isoformat()
    
    # Generate signature
    manager = LicenseManager()
    signature = manager._generate_signature(email, tier, expiry_str)
    
    # Create license key
    data = f"{email}|{tier}|{expiry_str}|{signature}"
    key = base64.b64encode(data.encode()).decode('utf-8')
    
    return key


if __name__ == "__main__":
    # Example: Generate a pro license key
    pro_key = generate_license_key(
        email="user@example.com",
        tier="pro",
        expiry=datetime.now() + timedelta(days=365)  # 1 year
    )
    print(f"Pro License Key: {pro_key}")
    
    # Test activation
    manager = LicenseManager()
    if manager.activate_license(pro_key):
        print("✓ License activated successfully!")
        print(f"Tier: {manager.get_tier().value}")
        print(f"Pro: {manager.is_pro()}")
