#!/usr/bin/env python3
"""
Profile Manager - Business Logic
Handles profile data management without UI dependencies
"""

import os
import json
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from datetime import datetime

# Import the user profile integration system
from user_profile_integration import UserProfileIntegration


@dataclass
class UserProfile:
    """User profile data structure"""
    name: str
    created_date: str
    last_played: str
    games_played: int = 0
    total_score: int = 0
    best_score: int = 0
    settings: Dict[str, Any] = None
    achievements: List[str] = None
    
    def __post_init__(self):
        if self.settings is None:
            self.settings = {
                "difficulty": "normal",
                "sound_volume": 50,
                "music_volume": 50,
                "screen_shake": True,
                "auto_save": True
            }
        if self.achievements is None:
            self.achievements = []


class ProfileDataManager:
    """Core business logic for profile management"""
    
    def __init__(self, profiles_file: str = "user_profiles.json"):
        self.profiles_file = profiles_file
        self.profiles: Dict[str, UserProfile] = {}
        self.active_profile: Optional[str] = None
        
        # Initialize user profile integration system
        self.integration = UserProfileIntegration(profiles_file)
        self.device_id = self.integration.get_device_id()
        self.api_enabled = self.integration.api_enabled
        
        self.load_profiles()
    
    def load_profiles(self) -> bool:
        """Load profiles from JSON file"""
        if not os.path.exists(self.profiles_file):
            return True
            
        try:
            with open(self.profiles_file, 'r') as f:
                data = json.load(f)
                self.profiles = {
                    name: UserProfile(**profile_data) 
                    for name, profile_data in data.get('profiles', {}).items()
                }
                self.active_profile = data.get('active_profile')
            return True
        except (json.JSONDecodeError, KeyError) as e:
            print(f"Error loading profiles: {e}")
            self.profiles = {}
            return False
    
    def save_profiles(self) -> bool:
        """Save profiles to JSON file"""
        data = {
            'profiles': {
                name: asdict(profile) 
                for name, profile in self.profiles.items()
            },
            'active_profile': self.active_profile
        }
        
        try:
            with open(self.profiles_file, 'w') as f:
                json.dump(data, f, indent=2)
            return True
        except IOError as e:
            print(f"Error saving profiles: {e}")
            return False
    
    def create_profile(self, name: str) -> tuple[bool, str]:
        """Create a new profile. Returns (success, message)"""
        name = name.strip()
        
        if not name:
            return False, "Profile name cannot be empty"
        
        if name in self.profiles:
            return False, f"Profile '{name}' already exists"
        
        now = datetime.now().isoformat()
        profile = UserProfile(
            name=name,
            created_date=now,
            last_played=now
        )
        
        self.profiles[name] = profile
        
        if not self.save_profiles():
            del self.profiles[name]
            return False, "Failed to save profile"
        
        # Register with API server if available
        if self.api_enabled:
            result = self.integration.register_new_user(name)
            if result:
                print(f"Profile {name} registered with server")
            else:
                print(f"Warning: Profile {name} created locally but not registered with server")
        
        return True, f"Profile '{name}' created successfully"
    
    def delete_profile(self, name: str) -> tuple[bool, str]:
        """Delete a profile. Returns (success, message)"""
        if name not in self.profiles:
            return False, f"Profile '{name}' not found"
        
        del self.profiles[name]
        
        if self.active_profile == name:
            self.active_profile = None
        
        if not self.save_profiles():
            return False, "Failed to save changes"
        
        return True, f"Profile '{name}' deleted"
    
    def set_active_profile(self, name: str) -> tuple[bool, str]:
        """Set the active profile. Returns (success, message)"""
        if name not in self.profiles:
            return False, f"Profile '{name}' not found"
        
        self.active_profile = name
        self.profiles[name].last_played = datetime.now().isoformat()
        
        if not self.save_profiles():
            return False, "Failed to save changes"
        
        # Update integration system to load the new profile
        self.integration.reload_profile()
        
        return True, f"Active profile set to '{name}'"
    
    def get_profile_list(self) -> List[str]:
        """Get list of profile names"""
        return list(self.profiles.keys())
    
    def get_profile(self, name: str) -> Optional[UserProfile]:
        """Get a specific profile"""
        return self.profiles.get(name)
    
    def get_active_profile(self) -> Optional[UserProfile]:
        """Get the currently active profile"""
        if self.active_profile:
            return self.profiles.get(self.active_profile)
        return None
    
    def update_profile_settings(self, name: str, setting: str, value: Any) -> tuple[bool, str]:
        """Update a profile setting. Returns (success, message)"""
        if name not in self.profiles:
            return False, f"Profile '{name}' not found"
        
        profile = self.profiles[name]
        
        if setting not in profile.settings:
            return False, f"Setting '{setting}' not found"
        
        # Validate setting values
        if not self._validate_setting(setting, value):
            return False, f"Invalid value for setting '{setting}'"
        
        profile.settings[setting] = value
        
        if not self.save_profiles():
            return False, "Failed to save changes"
        
        return True, f"Setting '{setting}' updated"
    
    def _validate_setting(self, setting: str, value: Any) -> bool:
        """Validate setting values"""
        validations = {
            'difficulty': lambda v: v in ['easy', 'normal', 'hard', 'expert'],
            'sound_volume': lambda v: isinstance(v, int) and 0 <= v <= 100,
            'music_volume': lambda v: isinstance(v, int) and 0 <= v <= 100,
            'screen_shake': lambda v: isinstance(v, bool),
            'auto_save': lambda v: isinstance(v, bool)
        }
        
        validator = validations.get(setting)
        return validator(value) if validator else True
    
    def get_leaderboard_data(self, leaderboard_type: str = "device") -> List[Dict[str, Any]]:
        """Get leaderboard data"""
        if not self.api_enabled:
            return []
        
        try:
            if leaderboard_type == "device":
                return self.integration.get_device_leaderboard(10)
            else:  # global
                return self.integration.get_global_leaderboard(10)
        except Exception as e:
            print(f"Error loading leaderboard: {e}")
            return []
    
    def get_profile_stats(self, name: str) -> Optional[Dict[str, Any]]:
        """Get detailed profile statistics"""
        if name not in self.profiles:
            return None
        
        profile = self.profiles[name]
        integration_info = self.integration.get_profile_info() if self.api_enabled else {}
        
        try:
            created = datetime.fromisoformat(profile.created_date).strftime("%Y-%m-%d")
            last_played = datetime.fromisoformat(profile.last_played).strftime("%Y-%m-%d")
        except:
            created = "Unknown"
            last_played = "Unknown"
        
        return {
            'profile': profile,
            'created_formatted': created,
            'last_played_formatted': last_played,
            'integration_info': integration_info,
            'api_enabled': self.api_enabled
        }


class SettingsManager:
    """Helper class for managing profile settings"""
    
    DIFFICULTY_OPTIONS = ["easy", "normal", "hard", "expert"]
    VOLUME_RANGE = (0, 100, 5)  # min, max, step
    
    @classmethod
    def adjust_difficulty(cls, current: str, direction: int) -> str:
        """Adjust difficulty setting"""
        try:
            current_index = cls.DIFFICULTY_OPTIONS.index(current)
            new_index = (current_index + direction) % len(cls.DIFFICULTY_OPTIONS)
            return cls.DIFFICULTY_OPTIONS[new_index]
        except ValueError:
            return "normal"
    
    @classmethod
    def adjust_volume(cls, current: int, direction: int) -> int:
        """Adjust volume setting"""
        min_val, max_val, step = cls.VOLUME_RANGE
        new_value = current + (direction * step)
        return max(min_val, min(max_val, new_value))
    
    @classmethod
    def toggle_boolean(cls, current: bool) -> bool:
        """Toggle boolean setting"""
        return not current
    
    @classmethod
    def get_setting_display_value(cls, setting: str, value: Any) -> str:
        """Get display string for setting value"""
        if setting == 'difficulty':
            return value.title()
        elif setting in ['sound_volume', 'music_volume']:
            return f"{value}%"
        elif setting in ['screen_shake', 'auto_save']:
            return "On" if value else "Off"
        else:
            return str(value)
