"""
REST API for web dashboard
"""
import os
import logging
import time
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, Optional, List
from flask import request, jsonify, g

from ..database.manager import DatabaseManager
from ..config.manager import ConfigManager
from ..core.message_bus import MessageBus, MessageBuilder, MessageType, Message

logger = logging.getLogger(__name__)


class DashboardAPI:
    """REST API endpoints for the dashboard"""
    
    def __init__(self, db_manager: DatabaseManager, config_manager: ConfigManager, 
                 message_bus: MessageBus):
        self.db_manager = db_manager
        self.config_manager = config_manager
        self.message_bus = message_bus
        
        logger.info("DashboardAPI initialized")
    
    def get_system_status(self) -> Dict[str, Any]:
        """Get system status"""
        try:
            # Get configuration status
            config_status = self.config_manager.validate_configuration()
            
            # Get database status
            db_status = self.db_manager.get_connection_status()
            
            # Get component status (cached or from message bus)
            components_status = self._get_components_status()
            
            return {
                "status": "online",
                "timestamp": datetime.utcnow().isoformat(),
                "uptime": time.time(),  # Would be actual uptime in production
                "config": config_status,
                "database": db_status,
                "components": components_status
            }
            
        except Exception as e:
            logger.error(f"Failed to get system status: {e}")
            return {
                "status": "error",
                "error": str(e),
                "timestamp": datetime.utcnow().isoformat()
            }
    
    def get_video_status(self) -> Dict[str, Any]:
        """Get video player status"""
        try:
            # Request status from video player
            status_request = Message(
                type=MessageType.STATUS_REQUEST,
                sender="web_dashboard",
                recipient="qt_player",
                data={}
            )
            self.message_bus.publish(status_request)
            
            # For now, return basic status
            # In full implementation, would wait for response or use cached status
            return {
                "player_status": "unknown",
                "current_file": None,
                "current_template": "news_template",
                "position": 0,
                "duration": 0,
                "volume": 100,
                "fullscreen": False
            }
            
        except Exception as e:
            logger.error(f"Failed to get video status: {e}")
            return {"error": str(e)}
    
    def control_video(self, action: str, **kwargs) -> Dict[str, Any]:
        """Control video player"""
        try:
            logger.info(f"Web Dashboard API control_video called - action: {action}, kwargs: {kwargs}")
            success = False
            
            if action == "play":
                file_path = kwargs.get("file_path", "")
                template = kwargs.get("template", "news_template")
                overlay_data = kwargs.get("overlay_data", {})
                
                # Convert relative path to absolute path
                if file_path and not os.path.isabs(file_path):
                    # Get the project root directory (where main.py is located)
                    project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
                    absolute_file_path = os.path.join(project_root, file_path)
                    logger.info(f"Converting relative path '{file_path}' to absolute path '{absolute_file_path}'")
                    file_path = absolute_file_path
                else:
                    logger.info(f"Using provided absolute path: {file_path}")
                
                # Verify file exists before sending to Qt player
                if file_path and not os.path.exists(file_path):
                    logger.error(f"Video file does not exist: {file_path}")
                    return {"error": f"Video file not found: {file_path}"}
                
                logger.info(f"Creating VIDEO_PLAY message - file_path: {file_path}, template: {template}")
                message = MessageBuilder.video_play(
                    sender="web_dashboard",
                    file_path=file_path,
                    template=template,
                    overlay_data=overlay_data
                )
                message.recipient = "qt_player"
                
                logger.info(f"Publishing VIDEO_PLAY message to qt_player")
                logger.info(f"Message data: {message.data}")
                logger.info(f"Message bus registered components: {list(self.message_bus._queues.keys()) if hasattr(self.message_bus, '_queues') else 'Unknown'}")
                
                publish_result = self.message_bus.publish(message)
                logger.info(f"Message bus publish result: {publish_result}")
                success = True
                
            elif action == "pause":
                message = Message(
                    type=MessageType.VIDEO_PAUSE,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={}
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "stop":
                message = Message(
                    type=MessageType.VIDEO_STOP,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={}
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "seek":
                position = kwargs.get("position", 0)
                message = Message(
                    type=MessageType.VIDEO_SEEK,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={"position": position}
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "volume":
                volume = kwargs.get("volume", 100)
                message = Message(
                    type=MessageType.VIDEO_VOLUME,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={"volume": volume}
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "fullscreen":
                fullscreen = kwargs.get("fullscreen", True)
                message = Message(
                    type=MessageType.VIDEO_FULLSCREEN,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={"fullscreen": fullscreen}
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "play_loop":
                file_path = kwargs.get("file_path") or kwargs.get("filename", "")
                template = kwargs.get("template", "news_template")
                overlay_data = kwargs.get("overlay_data", {})
                loop_count = kwargs.get("loop_count", -1)  # -1 for infinite loop
                
                # Convert relative path to absolute path
                if file_path and not os.path.isabs(file_path):
                    # Get the project root directory (where main.py is located)
                    project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
                    absolute_file_path = os.path.join(project_root, file_path)
                    logger.info(f"Converting relative path '{file_path}' to absolute path '{absolute_file_path}'")
                    file_path = absolute_file_path
                else:
                    logger.info(f"Using provided absolute path: {file_path}")
                
                # Verify file exists before sending to Qt player
                if file_path and not os.path.exists(file_path):
                    logger.error(f"Video file does not exist: {file_path}")
                    return {"error": f"Video file not found: {file_path}"}
                
                logger.info(f"Creating VIDEO_PLAY with infinite loop - file_path: {file_path}, template: {template}")
                
                # Create a custom loop message with explicit loop control
                message = Message(
                    type=MessageType.VIDEO_PLAY,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={
                        "file_path": file_path,
                        "template": template,
                        "overlay_data": overlay_data,
                        "action": "play_loop",  # Explicit action for Qt player
                        "loop_mode": True,
                        "infinite_loop": True,
                        "loop_count": -1,
                        "repeat": True,
                        "continuous_playback": True
                    }
                )
                
                logger.info(f"Publishing infinite loop message with data: {message.data}")
                self.message_bus.publish(message)
                success = True
                
            elif action == "stop_loop":
                message = Message(
                    type=MessageType.VIDEO_STOP,
                    sender="web_dashboard",
                    recipient="qt_player",
                    data={"stop_loop": True}  # Flag to indicate loop stop
                )
                self.message_bus.publish(message)
                success = True
                
            elif action == "template_change":
                template = kwargs.get("template")
                if not template:
                    return {"error": "Template is required for template_change action"}
                
                # Send template change message
                template_data = kwargs.get("template_data", {})
                template_data['reload_template'] = True
                template_data['load_specific_template'] = template
                
                message = MessageBuilder.template_change(
                    sender="web_dashboard",
                    template_name=template,
                    template_data=template_data
                )
                message.recipient = "qt_player"
                self.message_bus.publish(message)
                success = True
                
            else:
                return {"error": f"Unknown action: {action}"}
            
            if success:
                logger.info(f"Video control command sent successfully: {action}")
                return {"success": True, "action": action}
            else:
                logger.error("Failed to send video control command")
                return {"error": "Failed to send command"}
                
        except Exception as e:
            logger.error(f"Video control error: {e}")
            return {"error": str(e)}
    
    def update_overlay(self, template: str, data: Dict[str, Any]) -> Dict[str, Any]:
        """Update video overlay and load specific template"""
        try:
            # Send template change message to load the specific template
            template_data = data.copy()
            template_data['reload_template'] = True  # Flag to trigger template reload
            template_data['load_specific_template'] = template  # Specific template to load
            
            message = MessageBuilder.template_change(
                sender="web_dashboard",
                template_name=template,
                template_data=template_data
            )
            message.recipient = "qt_player"
            self.message_bus.publish(message)
            
            # Also send a separate overlay update message to ensure data is updated
            overlay_message = MessageBuilder.overlay_update(
                sender="web_dashboard",
                overlay_data=data
            )
            overlay_message.recipient = "qt_player"
            self.message_bus.publish(overlay_message)
            
            logger.info(f"Overlay update and template load sent: {template}")
            return {"success": True, "template": template, "loaded": True}
            
        except Exception as e:
            logger.error(f"Overlay update error: {e}")
            return {"error": str(e)}
    
    def get_templates(self) -> Dict[str, Any]:
        """Get available overlay templates from both built-in and uploaded directories"""
        try:
            from pathlib import Path
            
            # Get built-in templates directory
            builtin_templates_dir = Path(__file__).parent.parent / "qt_player" / "templates"
            
            # Get persistent uploaded templates directory
            uploaded_templates_dir = self._get_persistent_templates_dir()
            
            template_list = []
            templates_seen = set()
            
            # First scan uploaded templates (these take priority)
            if uploaded_templates_dir.exists():
                uploaded_files = list(uploaded_templates_dir.glob("*.html"))
                for html_file in uploaded_files:
                    template_name = html_file.stem
                    template_list.append({
                        "name": template_name,
                        "filename": html_file.name,
                        "display_name": template_name.replace("_", " ").title(),
                        "source": "uploaded",
                        "can_delete": True
                    })
                    templates_seen.add(template_name)
                logger.info(f"Found {len(uploaded_files)} uploaded templates in {uploaded_templates_dir}")
            
            # Then scan built-in templates (only add if not already seen from uploads)
            if builtin_templates_dir.exists():
                builtin_files = list(builtin_templates_dir.glob("*.html"))
                for html_file in builtin_files:
                    template_name = html_file.stem
                    if template_name not in templates_seen:
                        template_list.append({
                            "name": template_name,
                            "filename": html_file.name,
                            "display_name": template_name.replace("_", " ").title(),
                            "source": "builtin",
                            "can_delete": False
                        })
                        templates_seen.add(template_name)
                logger.info(f"Found {len(builtin_files)} built-in templates in {builtin_templates_dir}")
            else:
                logger.warning(f"Built-in templates directory not found: {builtin_templates_dir}")

            # Sort templates: uploaded first, then built-in
            template_list.sort(key=lambda t: (
                1 if t["source"] == "builtin" else 0,  # Uploaded before built-in
                t["name"]  # Alphabetical within each group
            ))

            return {"templates": template_list}
            
        except Exception as e:
            logger.error(f"Failed to get templates: {e}")
            return {"error": str(e)}
    
    def get_configuration(self, section: Optional[str] = None) -> Dict[str, Any]:
        """Get configuration data"""
        try:
            if section:
                config_data = self.config_manager.get_section_config(section)
                return {"section": section, "config": config_data}
            else:
                all_config = self.config_manager.get_all_config()
                return {"config": all_config}
                
        except Exception as e:
            logger.error(f"Failed to get configuration: {e}")
            return {"error": str(e)}
    
    def update_configuration(self, section: str, config_data: Dict[str, Any]) -> Dict[str, Any]:
        """Update configuration"""
        try:
            # Update configuration
            success = self.config_manager.update_section(section, config_data)
            
            if success:
                # Notify other components of configuration change
                message = Message(
                    type=MessageType.CONFIG_UPDATE,
                    sender="web_dashboard",
                    data={
                        "config_section": section,
                        "config_data": config_data
                    }
                )
                self.message_bus.publish(message)
                
                logger.info(f"Configuration updated: {section}")
                return {"success": True, "section": section}
            else:
                return {"error": "Failed to update configuration"}
                
        except Exception as e:
            logger.error(f"Configuration update error: {e}")
            return {"error": str(e)}
    
    def get_logs(self, level: str = "INFO", limit: int = 100) -> Dict[str, Any]:
        """Get application logs"""
        try:
            # This would normally read from log files or database
            # For now, return placeholder data
            logs = [
                {
                    "timestamp": datetime.utcnow().isoformat(),
                    "level": "INFO",
                    "component": "web_dashboard",
                    "message": "Dashboard started successfully"
                },
                {
                    "timestamp": datetime.utcnow().isoformat(),
                    "level": "INFO", 
                    "component": "qt_player",
                    "message": "Video player initialized"
                }
            ]
            
            return {"logs": logs[:limit]}
            
        except Exception as e:
            logger.error(f"Failed to get logs: {e}")
            return {"error": str(e)}
    
    def get_users(self) -> Dict[str, Any]:
        """Get all users (admin only)"""
        try:
            users = self.db_manager.get_all_users()
            user_list = [
                {
                    "id": user["id"],
                    "username": user["username"],
                    "email": user["email"],
                    "is_admin": user["is_admin"],
                    "role": user.get("role", "normal"),  # Include role field
                    "created_at": user["created_at"].isoformat() if user["created_at"] else None,
                    "last_login": user["last_login"].isoformat() if user["last_login"] else None
                }
                for user in users
            ]
            
            return {"users": user_list}
            
        except Exception as e:
            logger.error(f"Failed to get users: {e}")
            return {"error": str(e)}
    
    def create_user(self, username: str, email: str, password: str,
                   is_admin: bool = False, role: str = 'normal') -> Dict[str, Any]:
        """Create new user (admin only)"""
        try:
            from .auth import AuthManager
            
            # Get auth manager from Flask g context
            auth_manager = g.get('auth_manager')
            if not auth_manager:
                return {"error": "Auth manager not available"}
            
            user = auth_manager.create_user(username, email, password, is_admin, role)
            
            if user:
                return {
                    "success": True,
                    "user": {
                        "id": user["id"],
                        "username": user["username"],
                        "email": user["email"],
                        "is_admin": user["is_admin"],
                        "role": user.get("role", "normal")
                    }
                }
            else:
                return {"error": "Failed to create user"}
                
        except Exception as e:
            logger.error(f"User creation error: {e}")
            return {"error": str(e)}
    
    def update_user(self, user_id: int, username: str = None, email: str = None,
                   password: str = None, is_admin: bool = None, role: str = None) -> Dict[str, Any]:
        """Update user (admin only)"""
        try:
            from .auth import AuthManager
            
            # Get auth manager from Flask g context
            auth_manager = g.get('auth_manager')
            if not auth_manager:
                return {"error": "Auth manager not available"}
            
            user = auth_manager.update_user(user_id, username, email, password, is_admin, role)
            
            if user:
                return {
                    "success": True,
                    "user": {
                        "id": user["id"],
                        "username": user["username"],
                        "email": user["email"],
                        "is_admin": user["is_admin"],
                        "role": user.get("role", "normal")
                    }
                }
            else:
                return {"error": "Failed to update user"}
                
        except Exception as e:
            logger.error(f"User update error: {e}")
            return {"error": str(e)}
    
    def delete_user(self, user_id: int) -> Dict[str, Any]:
        """Delete user (admin only)"""
        try:
            success = self.db_manager.delete_user(user_id)
            
            if success:
                logger.info(f"User deleted: {user_id}")
                return {"success": True}
            else:
                return {"error": "Failed to delete user"}
                
        except Exception as e:
            logger.error(f"User deletion error: {e}")
            return {"error": str(e)}
    
    def get_api_tokens(self, user_id: int) -> List[Dict[str, Any]]:
        """Get API tokens for user"""
        try:
            from .auth import AuthManager
            
            auth_manager = g.get('auth_manager')
            if not auth_manager:
                return {"error": "Auth manager not available"}
            
            tokens = auth_manager.list_user_tokens(user_id)
            
            # Add token preview for each token (first 8 chars + ... + last 4 chars)
            for token_data in tokens:
                # We don't store the actual token, so create a fake preview
                token_data['token_preview'] = f"{'*' * 8}...{'*' * 4}"
                # We can't show the actual token since it's hashed
                token_data['token'] = "[Hidden - Token only shown once during creation]"
            
            return tokens
            
        except Exception as e:
            logger.error(f"Failed to get API tokens: {e}")
            return []
    
    def create_api_token(self, user_id: int, token_name: str, 
                        expires_hours: int = 8760) -> Dict[str, Any]:
        """Create API token"""
        try:
            from .auth import AuthManager
            
            auth_manager = g.get('auth_manager')
            if not auth_manager:
                return {"error": "Auth manager not available"}
            
            result = auth_manager.create_api_token(user_id, token_name, expires_hours)
            
            if result:
                token, token_data = result
                return {
                    "success": True,
                    "token": token,
                    "token_info": {
                        "id": token_data['id'],
                        "name": token_data['name'],
                        "expires_at": token_data['expires_at'].isoformat() if isinstance(token_data['expires_at'], datetime) else token_data['expires_at']
                    }
                }
            else:
                return {"error": "Failed to create API token"}
                
        except Exception as e:
            logger.error(f"API token creation error: {e}")
            return {"error": str(e)}
    
    def revoke_api_token(self, user_id: int, token_id: int) -> Dict[str, Any]:
        """Revoke API token"""
        try:
            from .auth import AuthManager
            
            auth_manager = g.get('auth_manager')
            if not auth_manager:
                return {"error": "Auth manager not available"}
            
            success = auth_manager.revoke_api_token_by_id(token_id, user_id)
            
            if success:
                return {"success": True}
            else:
                return {"error": "Failed to revoke token"}
                
        except Exception as e:
            logger.error(f"API token revocation error: {e}")
            return {"error": str(e)}
    
    def _get_components_status(self) -> Dict[str, Any]:
        """Get status of all components"""
        try:
            from flask import g
            
            # Get main application from Flask context
            main_app = g.get('main_app')
            if main_app and hasattr(main_app, 'thread_manager'):
                # Get real component status from thread manager
                components_status = {}
                
                # Get all registered components
                component_names = main_app.thread_manager.get_component_names()
                
                for component_name in component_names:
                    if main_app.thread_manager.is_component_running(component_name):
                        if main_app.thread_manager.is_component_healthy(component_name):
                            components_status[component_name] = "running"
                        else:
                            components_status[component_name] = "unhealthy"
                    else:
                        components_status[component_name] = "stopped"
                
                # Always show web dashboard as running since we're responding
                components_status["web_dashboard"] = "running"
                
                # Always show message bus as running since we can query it
                components_status["message_bus"] = "running"
                
                return components_status
            else:
                # Fallback to hardcoded values if main app not available
                return {
                    "qt_player": "unknown",
                    "web_dashboard": "running",
                    "api_client": "unknown",
                    "message_bus": "running"
                }
        except Exception as e:
            logger.error(f"Failed to get real component status: {e}")
            # Fallback to hardcoded values on error
            return {
                "qt_player": "unknown",
                "web_dashboard": "running",
                "api_client": "unknown",
                "message_bus": "running"
            }
    
    def send_test_message(self, recipient: str, message_type: str, 
                         data: Dict[str, Any]) -> Dict[str, Any]:
        """Send test message to component (admin only)"""
        try:
            # Map string message types to enum
            type_mapping = {
                "video_play": MessageType.VIDEO_PLAY,
                "video_pause": MessageType.VIDEO_PAUSE,
                "video_stop": MessageType.VIDEO_STOP,
                "config_update": MessageType.CONFIG_UPDATE,
                "system_status": MessageType.SYSTEM_STATUS,
            }
            
            msg_type = type_mapping.get(message_type)
            if not msg_type:
                return {"error": f"Unknown message type: {message_type}"}
            
            message = Message(
                type=msg_type,
                sender="web_dashboard",
                recipient=recipient,
                data=data
            )
            
            self.message_bus.publish(message)
            
            logger.info(f"Test message sent: {message_type} to {recipient}")
            return {"success": True, "message_type": message_type, "recipient": recipient}
            
        except Exception as e:
            logger.error(f"Test message error: {e}")
            return {"error": str(e)}
    
    def upload_video(self, file_data, template: str) -> Dict[str, Any]:
        """Handle video upload"""
        try:
            import os
            import uuid
            from werkzeug.utils import secure_filename
            from pathlib import Path
            
            logger.info(f"API upload_video called with file_data type: {type(file_data)}")
            logger.info(f"Starting video upload - filename: {getattr(file_data, 'filename', 'NO_FILENAME')}, template: {template}")
            
            # Validate file data
            if not file_data:
                logger.error("No file data provided")
                return {"error": "No file provided"}
            
            if not file_data.filename:
                logger.error("No filename provided")
                return {"error": "No filename provided"}
            
            # Get project root directory (where main.py is located)
            project_root = Path(__file__).parent.parent.parent
            upload_dir = project_root / 'uploads'
            
            logger.info(f"Project root: {project_root}")
            logger.info(f"Upload directory: {upload_dir}")
            
            # Create uploads directory if it doesn't exist
            try:
                upload_dir.mkdir(parents=True, exist_ok=True)
                logger.info(f"Upload directory created/verified: {upload_dir}")
            except Exception as dir_error:
                logger.error(f"Failed to create upload directory: {dir_error}")
                return {"error": f"Failed to create upload directory: {str(dir_error)}"}
            
            # Generate secure filename
            original_filename = secure_filename(file_data.filename)
            if not original_filename:
                logger.warning("Filename could not be secured, generating UUID")
                original_filename = str(uuid.uuid4()) + ".mp4"
            
            # Add timestamp to make filename unique
            name, ext = os.path.splitext(original_filename)
            if not ext:
                ext = ".mp4"  # Default extension for video files
            unique_filename = f"{name}_{int(time.time())}{ext}"
            
            logger.info(f"Original filename: {file_data.filename}")
            logger.info(f"Secured filename: {original_filename}")
            logger.info(f"Unique filename: {unique_filename}")
            
            # Construct full file path
            file_path = upload_dir / unique_filename
            
            # Check if file already exists (shouldn't happen with timestamp, but safety check)
            if file_path.exists():
                logger.warning(f"File already exists, adding extra UUID: {file_path}")
                name_with_uuid = f"{name}_{int(time.time())}_{str(uuid.uuid4())[:8]}"
                unique_filename = f"{name_with_uuid}{ext}"
                file_path = upload_dir / unique_filename
            
            # Save the file
            try:
                logger.info(f"Saving file to: {file_path}")
                file_data.save(str(file_path))
                
                # Verify file was saved successfully
                if not file_path.exists():
                    logger.error(f"File was not saved successfully: {file_path}")
                    return {"error": "File was not saved successfully"}
                
                file_size = file_path.stat().st_size
                logger.info(f"File saved successfully - size: {file_size} bytes")
                
                if file_size == 0:
                    logger.error("Saved file is empty")
                    return {"error": "Uploaded file is empty"}
                
            except Exception as save_error:
                logger.error(f"Failed to save file: {save_error}")
                return {"error": f"Failed to save file: {str(save_error)}"}
            
            # Return relative path for the web interface (will be converted to absolute when playing)
            relative_path = f"uploads/{unique_filename}"
            
            logger.info(f"Video uploaded successfully:")
            logger.info(f"  - Saved to: {file_path}")
            logger.info(f"  - File size: {file_size} bytes")
            logger.info(f"  - Relative path: {relative_path}")
            logger.info(f"  - Template: {template}")
            
            return {
                "success": True,
                "filename": relative_path,
                "original_filename": file_data.filename,
                "size": file_size,
                "template": template,
                "message": "Video uploaded successfully"
            }
            
        except Exception as e:
            logger.error(f"Video upload error: {e}", exc_info=True)
            return {"error": str(e)}
    
    def delete_video(self, filename: str) -> Dict[str, Any]:
        """Delete uploaded video"""
        try:
            import os
            
            # Construct full path
            file_path = os.path.join(os.path.dirname(__file__), '..', '..', filename)
            
            # Check if file exists
            if os.path.exists(file_path):
                os.remove(file_path)
                logger.info(f"Video deleted: {filename}")
                return {"success": True, "message": "Video deleted successfully"}
            else:
                return {"error": "File not found"}
                
        except Exception as e:
            logger.error(f"Video deletion error: {e}")
            return {"error": str(e)}
    
    def _get_persistent_templates_dir(self) -> Path:
        """Get persistent templates directory for user uploads"""
        try:
            import platform
            from pathlib import Path
            
            system = platform.system()
            
            if system == "Windows":
                # Use AppData/Roaming on Windows
                app_data = os.getenv('APPDATA', os.path.expanduser('~'))
                templates_dir = Path(app_data) / "MbetterClient" / "templates"
            elif system == "Darwin":  # macOS
                # Use ~/Library/Application Support on macOS
                templates_dir = Path.home() / "Library" / "Application Support" / "MbetterClient" / "templates"
            else:  # Linux and other Unix-like systems
                # Use ~/.config on Linux
                config_home = os.getenv('XDG_CONFIG_HOME', str(Path.home() / ".config"))
                templates_dir = Path(config_home) / "MbetterClient" / "templates"
            
            logger.debug(f"Persistent templates directory: {templates_dir}")
            return templates_dir
                
        except Exception as e:
            logger.error(f"Failed to determine persistent templates directory: {e}")
            # Fallback to local directory
            return Path.cwd() / "user_templates"
    
    def upload_template(self, file_data, template_name: str = None) -> Dict[str, Any]:
        """Upload template file to persistent directory"""
        try:
            from werkzeug.utils import secure_filename
            
            # Get persistent templates directory
            templates_dir = self._get_persistent_templates_dir()
            templates_dir.mkdir(parents=True, exist_ok=True)
            
            # Secure the filename
            filename = secure_filename(file_data.filename)
            if not filename:
                return {"error": "Invalid filename"}
            
            # Ensure .html extension
            if not filename.lower().endswith('.html'):
                filename += '.html'
            
            # Use provided template name or derive from filename
            if template_name:
                filename = secure_filename(template_name)
                if not filename.lower().endswith('.html'):
                    filename += '.html'
            
            # Save to persistent templates directory
            file_path = templates_dir / filename
            file_data.save(str(file_path))
            
            logger.info(f"Template uploaded successfully: {file_path}")
            
            return {
                "success": True,
                "message": "Template uploaded successfully",
                "filename": filename,
                "template_name": Path(filename).stem
            }
            
        except Exception as e:
            logger.error(f"Template upload error: {e}")
            return {"error": str(e)}
    
    def delete_template(self, template_name: str) -> Dict[str, Any]:
        """Delete uploaded template file"""
        try:
            # Only allow deletion of uploaded templates, not built-in ones
            templates_dir = self._get_persistent_templates_dir()

            # Add .html extension if not present
            if not template_name.endswith('.html'):
                template_name += '.html'

            template_path = templates_dir / template_name

            if not template_path.exists():
                return {"error": "Template not found in uploaded templates"}

            # Delete the file
            template_path.unlink()

            logger.info(f"Template deleted: {template_path}")

            return {
                "success": True,
                "message": "Template deleted successfully",
                "template_name": Path(template_name).stem
            }

        except Exception as e:
            logger.error(f"Template deletion error: {e}")
            return {"error": str(e)}

    def get_template_preview(self, template_name: str) -> str:
        """Get template HTML content for preview with black background"""
        try:
            from pathlib import Path

            # Get built-in templates directory
            builtin_templates_dir = Path(__file__).parent.parent / "qt_player" / "templates"

            # Get persistent uploaded templates directory
            uploaded_templates_dir = self._get_persistent_templates_dir()

            # Add .html extension if not present
            if not template_name.endswith('.html'):
                template_name += '.html'

            template_path = None

            # First check uploaded templates (they take priority)
            uploaded_path = uploaded_templates_dir / template_name
            if uploaded_path.exists():
                template_path = uploaded_path
                logger.info(f"Found uploaded template for preview: {template_path}")
            else:
                # Check built-in templates
                builtin_path = builtin_templates_dir / template_name
                if builtin_path.exists():
                    template_path = builtin_path
                    logger.info(f"Found built-in template for preview: {template_path}")
                else:
                    # Try without .html extension
                    template_name_no_ext = template_name.replace('.html', '')
                    builtin_path_no_ext = builtin_templates_dir / f"{template_name_no_ext}.html"
                    if builtin_path_no_ext.exists():
                        template_path = builtin_path_no_ext
                        logger.info(f"Found built-in template for preview (added .html): {template_path}")

            if not template_path or not template_path.exists():
                logger.error(f"Template not found for preview: {template_name}")
                return self._get_template_not_found_html(template_name)

            # Read template content
            try:
                with open(template_path, 'r', encoding='utf-8') as f:
                    template_html = f.read()
            except Exception as e:
                logger.error(f"Failed to read template file: {e}")
                return self._get_template_error_html(template_name, str(e))

            # Wrap template in black background container
            preview_html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Template Preview: {template_name.replace('.html', '')}</title>
    <style>
        body {{
            margin: 0;
            padding: 20px;
            background-color: #000000;
            color: #ffffff;
            font-family: Arial, sans-serif;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
        }}

        .preview-container {{
            width: 100%;
            max-width: 1920px;
            background-color: #000000;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
        }}

        .preview-header {{
            text-align: center;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 1px solid #333;
        }}

        .preview-title {{
            font-size: 24px;
            font-weight: bold;
            color: #ffffff;
            margin: 0;
        }}

        .preview-subtitle {{
            font-size: 16px;
            color: #cccccc;
            margin: 5px 0 0 0;
        }}

        .template-content {{
            width: 100%;
            background-color: #000000 !important;
            border-radius: 4px;
            overflow: hidden;
        }}

        /* Force black background on ALL elements */
        .template-content,
        .template-content *,
        .template-content body,
        .template-content html,
        .template-content div,
        .template-content span,
        .template-content p,
        .template-content h1,
        .template-content h2,
        .template-content h3,
        .template-content h4,
        .template-content h5,
        .template-content h6 {{
            background-color: #000000 !important;
            background: #000000 !important;
        }}

        /* Override any background styles in the template */
        .template-content [style*="background-color"],
        .template-content [style*="background:"] {{
            background-color: #000000 !important;
            background: #000000 !important;
        }}

        /* Specific overrides for common background colors */
        .template-content [style*="background-color: white"],
        .template-content [style*="background-color: #fff"],
        .template-content [style*="background-color: #ffffff"],
        .template-content [style*="background: white"],
        .template-content [style*="background: #fff"],
        .template-content [style*="background: #ffffff"] {{
            background-color: #000000 !important;
            background: #000000 !important;
        }}

        /* Make sure text is visible on black background */
        .template-content [style*="color: black"],
        .template-content [style*="color: #000"],
        .template-content [style*="color: #000000"] {{
            color: #ffffff !important;
        }}

        /* Force all text to be white for visibility */
        .template-content * {{
            color: #ffffff !important;
        }}

        /* Override any white text that might be invisible on black */
        .template-content [style*="color: white"],
        .template-content [style*="color: #fff"],
        .template-content [style*="color: #ffffff"] {{
            color: #ffffff !important;
        }}
    </style>
</head>
<body>
    <div class="preview-container">
        <div class="preview-header">
            <h1 class="preview-title">Template Preview</h1>
            <p class="preview-subtitle">{template_name.replace('.html', '')}</p>
        </div>
        <div class="template-content" id="template-content">
            {template_html}
        </div>
    </div>

    <script>
        // Force black background on all elements after page load
        document.addEventListener('DOMContentLoaded', function() {{
            function forceBlackBackground(element) {{
                if (element) {{
                    element.style.backgroundColor = '#000000';
                    element.style.background = '#000000';

                    // Force all child elements to have black background
                    const allElements = element.querySelectorAll('*');
                    allElements.forEach(function(el) {{
                        el.style.backgroundColor = '#000000';
                        el.style.background = '#000000';
                        el.style.color = '#ffffff';
                    }});
                }}
            }}

            // Force black background on template content
            const templateContent = document.getElementById('template-content');
            forceBlackBackground(templateContent);

            // Also force on body and html elements within the template
            const templateBody = templateContent.querySelector('body');
            const templateHtml = templateContent.querySelector('html');

            if (templateBody) {{
                templateBody.style.backgroundColor = '#000000';
                templateBody.style.background = '#000000';
            }}

            if (templateHtml) {{
                templateHtml.style.backgroundColor = '#000000';
                templateHtml.style.background = '#000000';
            }}

            // Continuous enforcement every 100ms for 2 seconds
            let enforcementCount = 0;
            const maxEnforcements = 20;

            const enforceInterval = setInterval(function() {{
                forceBlackBackground(templateContent);
                enforcementCount++;

                if (enforcementCount >= maxEnforcements) {{
                    clearInterval(enforceInterval);
                }}
            }}, 100);
        }});
    </script>
</body>
</html>
"""

            logger.info(f"Generated template preview for: {template_name}")
            return preview_html

        except Exception as e:
            logger.error(f"Failed to generate template preview: {e}")
            return self._get_template_error_html(template_name, str(e))

    def _get_template_not_found_html(self, template_name: str) -> str:
        """Get HTML for template not found error"""
        return f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Template Not Found</title>
    <style>
        body {{
            margin: 0;
            padding: 20px;
            background-color: #000000;
            color: #ffffff;
            font-family: Arial, sans-serif;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }}

        .error-container {{
            text-align: center;
            background-color: #1a1a1a;
            padding: 40px;
            border-radius: 8px;
            box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
            max-width: 500px;
        }}

        .error-title {{
            font-size: 24px;
            color: #ff6b6b;
            margin-bottom: 20px;
        }}

        .error-message {{
            font-size: 16px;
            color: #cccccc;
        }}
    </style>
</head>
<body>
    <div class="error-container">
        <h1 class="error-title">Template Not Found</h1>
        <p class="error-message">The template "{template_name}" could not be found.</p>
    </div>
</body>
</html>
"""

    def _get_template_error_html(self, template_name: str, error: str) -> str:
        """Get HTML for template error"""
        return f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Template Error</title>
    <style>
        body {{
            margin: 0;
            padding: 20px;
            background-color: #000000;
            color: #ffffff;
            font-family: Arial, sans-serif;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }}

        .error-container {{
            text-align: center;
            background-color: #1a1a1a;
            padding: 40px;
            border-radius: 8px;
            box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
            max-width: 500px;
        }}

        .error-title {{
            font-size: 24px;
            color: #ff6b6b;
            margin-bottom: 20px;
        }}

        .error-message {{
            font-size: 16px;
            color: #cccccc;
            margin-bottom: 10px;
        }}

        .error-details {{
            font-size: 14px;
            color: #888;
            font-family: monospace;
            background-color: #2a2a2a;
            padding: 10px;
            border-radius: 4px;
            text-align: left;
            white-space: pre-wrap;
            word-break: break-all;
        }}
    </style>
</head>
<body>
    <div class="error-container">
        <h1 class="error-title">Template Error</h1>
        <p class="error-message">Error loading template "{template_name}"</p>
        <div class="error-details">{error}</div>
    </div>
</body>
</html>
"""


# Route functions for Flask
def get_config_section(section):
    """Get configuration section"""
    try:
        api = g.get('api')
        if not api:
            return jsonify({"error": "API not available"}), 500
            
        result = api.get_configuration(section)
        if "error" in result:
            return jsonify(result), 500
        else:
            return jsonify(result)
            
    except Exception as e:
        logger.error(f"Route get_config_section error: {e}")
        return jsonify({"error": str(e)}), 500


def update_config_section(section):
    """Update configuration section"""
    try:
        api = g.get('api')
        if not api:
            return jsonify({"error": "API not available"}), 500
            
        data = request.get_json() or {}
        result = api.update_configuration(section, data)
        
        if "error" in result:
            return jsonify(result), 500
        else:
            return jsonify(result)
            
    except Exception as e:
        logger.error(f"Route update_config_section error: {e}")
        return jsonify({"error": str(e)}), 500
