"""
Template Helpers für MYP Platform
Jinja2 Helper-Funktionen für UI-Komponenten
"""

from flask import current_app, url_for, request
from markupsafe import Markup
import json
from datetime import datetime
from typing import Dict, Any, Optional, List
import calendar
import random


class UIHelpers:
    """UI-Helper-Klasse für Template-Funktionen"""
    
    @staticmethod
    def component_button(text: str, type: str = "primary", size: str = "md", 
                        classes: str = "", icon: str = "", onclick: str = "", 
                        disabled: bool = False, **attrs) -> Markup:
        """
        Erstellt einen Button mit Tailwind-Klassen
        
        Args:
            text: Button-Text
            type: Button-Typ (primary, secondary, danger, success)
            size: Button-Größe (sm, md, lg)
            classes: Zusätzliche CSS-Klassen
            icon: SVG-Icon-Code
            onclick: JavaScript-Code für onclick
            disabled: Button deaktiviert
            **attrs: Zusätzliche HTML-Attribute
        """
        base_classes = ["btn"]
        
        # Typ-spezifische Klassen
        type_classes = {
            "primary": "btn-primary",
            "secondary": "btn-secondary", 
            "danger": "btn-danger",
            "success": "btn-success"
        }
        base_classes.append(type_classes.get(type, "btn-primary"))
        
        # Größen-spezifische Klassen
        size_classes = {
            "sm": "btn-sm",
            "md": "",
            "lg": "btn-lg"
        }
        if size_classes.get(size):
            base_classes.append(size_classes[size])
            
        if disabled:
            base_classes.append("opacity-50 cursor-not-allowed")
            
        # Zusätzliche Klassen hinzufügen
        if classes:
            base_classes.append(classes)
            
        # HTML-Attribute aufbauen
        attrs_str = ""
        for key, value in attrs.items():
            attrs_str += f' {key.replace("_", "-")}="{value}"'
            
        if onclick:
            attrs_str += f' onclick="{onclick}"'
            
        if disabled:
            attrs_str += ' disabled'
            
        # Icon und Text kombinieren
        content = ""
        if icon:
            content += f'<span class="inline-block mr-2">{icon}</span>'
        content += text
        
        html = f'''<button class="{" ".join(base_classes)}"{attrs_str}>
            {content}
        </button>'''
        
        return Markup(html)
    
    @staticmethod
    def component_badge(text: str, type: str = "blue", classes: str = "") -> Markup:
        """
        Erstellt ein Badge/Tag-Element
        
        Args:
            text: Badge-Text
            type: Badge-Typ (blue, green, red, yellow, purple)
            classes: Zusätzliche CSS-Klassen
        """
        base_classes = ["badge", f"badge-{type}"]
        
        if classes:
            base_classes.append(classes)
            
        html = f'<span class="{" ".join(base_classes)}">{text}</span>'
        return Markup(html)
    
    @staticmethod
    def component_status_badge(status: str, type: str = "job") -> Markup:
        """
        Erstellt ein Status-Badge für Jobs oder Drucker
        
        Args:
            status: Status-Wert
            type: Typ (job, printer)
        """
        if type == "job":
            class_name = f"job-status job-{status}"
        else:
            class_name = f"printer-status printer-{status}"
            
        # Status-Text übersetzen
        translations = {
            "job": {
                "queued": "In Warteschlange",
                "printing": "Wird gedruckt", 
                "completed": "Abgeschlossen",
                "failed": "Fehlgeschlagen",
                "cancelled": "Abgebrochen",
                "paused": "Pausiert"
            },
            "printer": {
                "ready": "Bereit",
                "busy": "Beschäftigt",
                "error": "Fehler",
                "offline": "Offline",
                "maintenance": "Wartung"
            }
        }
        
        display_text = translations.get(type, {}).get(status, status)
        
        html = f'<span class="{class_name}">{display_text}</span>'
        return Markup(html)
    
    @staticmethod
    def component_card(title: str = "", content: str = "", footer: str = "", 
                      classes: str = "", hover: bool = False) -> Markup:
        """
        Erstellt eine Karte
        
        Args:
            title: Karten-Titel
            content: Karten-Inhalt
            footer: Karten-Footer
            classes: Zusätzliche CSS-Klassen
            hover: Hover-Effekt aktivieren
        """
        base_classes = ["card"]
        
        if hover:
            base_classes.append("card-hover")
            
        if classes:
            base_classes.append(classes)
            
        html_parts = [f'<div class="{" ".join(base_classes)}">']
        
        if title:
            html_parts.append(f'<h3 class="text-lg font-semibold mb-4 text-slate-900 dark:text-white">{title}</h3>')
            
        if content:
            html_parts.append(f'<div class="text-slate-600 dark:text-slate-300">{content}</div>')
            
        if footer:
            html_parts.append(f'<div class="mt-4 pt-4 border-t border-light-border dark:border-dark-border">{footer}</div>')
            
        html_parts.append('</div>')
        
        return Markup("".join(html_parts))
    
    @staticmethod
    def component_alert(message: str, type: str = "info", dismissible: bool = False) -> Markup:
        """
        Erstellt eine Alert-Benachrichtigung
        
        Args:
            message: Alert-Nachricht
            type: Alert-Typ (info, success, warning, error)
            dismissible: Schließbar machen
        """
        base_classes = ["alert", f"alert-{type}"]
        
        html_parts = [f'<div class="{" ".join(base_classes)}">']
        
        if dismissible:
            html_parts.append('''
                <div class="flex justify-between">
                    <div>
            ''')
        
        html_parts.append(f'<p>{message}</p>')
        
        if dismissible:
            html_parts.append('''
                    </div>
                    <button onclick="this.parentElement.parentElement.remove()" 
                            class="text-current opacity-70 hover:opacity-100">
                        <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
                            <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
                        </svg>
                    </button>
                </div>
            ''')
        
        html_parts.append('</div>')
        
        return Markup("".join(html_parts))
    
    @staticmethod
    def component_modal(modal_id: str, title: str, content: str, 
                       footer: str = "", size: str = "md") -> Markup:
        """
        Erstellt ein Modal-Dialog
        
        Args:
            modal_id: Eindeutige Modal-ID
            title: Modal-Titel
            content: Modal-Inhalt
            footer: Modal-Footer
            size: Modal-Größe (sm, md, lg, xl)
        """
        size_classes = {
            "sm": "max-w-md",
            "md": "max-w-lg", 
            "lg": "max-w-2xl",
            "xl": "max-w-4xl"
        }
        
        max_width = size_classes.get(size, "max-w-lg")
        
        html = f'''
        <div id="{modal_id}" class="fixed inset-0 z-50 hidden">
            <div class="flex items-center justify-center min-h-screen px-4">
                <div class="modal-content bg-white dark:bg-slate-800 rounded-lg shadow-xl transform scale-95 opacity-0 transition-all duration-150 w-full {max_width}">
                    <div class="px-6 py-4 border-b border-slate-200 dark:border-slate-700">
                        <div class="flex items-center justify-between">
                            <h3 class="text-lg font-semibold text-slate-900 dark:text-white">{title}</h3>
                            <button data-modal-close="{modal_id}" class="text-slate-400 hover:text-slate-600 dark:hover:text-slate-300">
                                <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
                                </svg>
                            </button>
                        </div>
                    </div>
                    <div class="px-6 py-4">
                        {content}
                    </div>
                    {f'<div class="px-6 py-4 border-t border-slate-200 dark:border-slate-700">{footer}</div>' if footer else ''}
                </div>
            </div>
        </div>
        '''
        
        return Markup(html)
    
    @staticmethod
    def component_table(headers: List[str], rows: List[List[str]], 
                       classes: str = "", striped: bool = True) -> Markup:
        """
        Erstellt eine styled Tabelle
        
        Args:
            headers: Tabellen-Kopfzeilen
            rows: Tabellen-Zeilen
            classes: Zusätzliche CSS-Klassen  
            striped: Zebra-Streifen aktivieren
        """
        html_parts = ['<div class="table-container">']
        
        table_classes = ["table-styled"]
        if classes:
            table_classes.append(classes)
            
        html_parts.append(f'<table class="{" ".join(table_classes)}">')
        
        # Kopfzeilen
        html_parts.append('<thead><tr>')
        for header in headers:
            html_parts.append(f'<th>{header}</th>')
        html_parts.append('</tr></thead>')
        
        # Zeilen
        html_parts.append('<tbody>')
        for i, row in enumerate(rows):
            row_classes = ""
            if striped and i % 2 == 1:
                row_classes = 'class="bg-slate-50 dark:bg-slate-800/50"'
            html_parts.append(f'<tr {row_classes}>')
            for cell in row:
                html_parts.append(f'<td>{cell}</td>')
            html_parts.append('</tr>')
        html_parts.append('</tbody>')
        
        html_parts.append('</table></div>')
        
        return Markup("".join(html_parts))
    
    @staticmethod
    def format_datetime_german(dt: datetime, format_str: str = "%d.%m.%Y %H:%M") -> str:
        """
        Formatiert Datetime für deutsche Anzeige
        
        Args:
            dt: Datetime-Objekt
            format_str: Format-String
        """
        if not dt:
            return ""
        return dt.strftime(format_str)
    
    @staticmethod
    def format_duration(minutes: int) -> str:
        """
        Formatiert Dauer in Minuten zu lesbarem Format
        
        Args:
            minutes: Dauer in Minuten
        """
        if not minutes:
            return "0 Min"
            
        if minutes < 60:
            return f"{minutes} Min"
        
        hours = minutes // 60
        remaining_minutes = minutes % 60
        
        if remaining_minutes == 0:
            return f"{hours} Std"
        
        return f"{hours} Std {remaining_minutes} Min"
    
    @staticmethod
    def json_encode(data: Any) -> str:
        """
        Enkodiert Python-Daten als JSON für JavaScript
        
        Args:
            data: Zu enkodierendes Objekt
        """
        return json.dumps(data, default=str, ensure_ascii=False)


def register_template_helpers(app):
    """
    Registriert alle Template-Helper bei der Flask-App
    
    Args:
        app: Flask-App-Instanz
    """
    # Funktionen registrieren
    app.jinja_env.globals['ui_button'] = UIHelpers.component_button
    app.jinja_env.globals['ui_badge'] = UIHelpers.component_badge
    app.jinja_env.globals['ui_status_badge'] = UIHelpers.component_status_badge
    app.jinja_env.globals['ui_card'] = UIHelpers.component_card
    app.jinja_env.globals['ui_alert'] = UIHelpers.component_alert
    app.jinja_env.globals['ui_modal'] = UIHelpers.component_modal
    app.jinja_env.globals['ui_table'] = UIHelpers.component_table
    
    # Filter registrieren
    app.jinja_env.filters['german_datetime'] = UIHelpers.format_datetime_german
    app.jinja_env.filters['duration'] = UIHelpers.format_duration
    app.jinja_env.filters['json'] = UIHelpers.json_encode
    
    # Zusätzliche globale Variablen
    app.jinja_env.globals['current_year'] = datetime.now().year
    
    # Icons als globale Variablen
    icons = {
        'check': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>',
        'x': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>',
        'plus': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>',
        'edit': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg>',
        'trash': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>',
        'printer': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z"></path></svg>',
        'dashboard': '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"></path></svg>',
    }
    
    app.jinja_env.globals['icons'] = icons 

    @app.context_processor
    def utility_processor():
        """Fügt nützliche Hilfsfunktionen zu Jinja hinzu."""
        return dict(
            active_page=active_page,
            format_datetime=format_datetime,
            format_date=format_date,
            format_time=format_time,
            random_avatar_color=random_avatar_color,
            get_initials=get_initials,
            render_progress_bar=render_progress_bar
        )

def active_page(path):
    """
    Überprüft, ob der aktuelle Pfad mit dem gegebenen Pfad übereinstimmt.
    """
    if request.path == path:
        return 'active'
    return ''

def format_datetime(value, format='%d.%m.%Y %H:%M'):
    """
    Formatiert ein Datum mit Uhrzeit nach deutschem Format.
    """
    if value is None:
        return ""
    if isinstance(value, str):
        try:
            value = datetime.fromisoformat(value)
        except ValueError:
            return value
    return value.strftime(format)

def format_date(value, format='%d.%m.%Y'):
    """
    Formatiert ein Datum nach deutschem Format.
    """
    if value is None:
        return ""
    if isinstance(value, str):
        try:
            value = datetime.fromisoformat(value)
        except ValueError:
            return value
    return value.strftime(format)

def format_time(value, format='%H:%M'):
    """
    Formatiert eine Uhrzeit nach deutschem Format.
    """
    if value is None:
        return ""
    if isinstance(value, str):
        try:
            value = datetime.fromisoformat(value)
        except ValueError:
            return value
    return value.strftime(format)

def random_avatar_color():
    """
    Gibt eine zufällige Hintergrundfarbe für Avatare zurück.
    """
    colors = [
        'bg-blue-100 text-blue-800',
        'bg-green-100 text-green-800',
        'bg-yellow-100 text-yellow-800',
        'bg-red-100 text-red-800',
        'bg-indigo-100 text-indigo-800',
        'bg-purple-100 text-purple-800',
        'bg-pink-100 text-pink-800',
        'bg-gray-100 text-gray-800',
    ]
    return random.choice(colors)

def get_initials(name, max_length=2):
    """
    Extrahiert die Initialen eines Namens.
    """
    if not name:
        return "?"
    
    parts = name.split()
    if len(parts) == 1:
        return name[0:max_length].upper()
    
    initials = ""
    for part in parts:
        if part and len(initials) < max_length:
            initials += part[0].upper()
    
    return initials

def render_progress_bar(value, color='blue'):
    """
    Rendert einen Fortschrittsbalken ohne Inline-Styles.
    
    Args:
        value (int): Der Prozentwert für den Fortschrittsbalken (0-100)
        color (str): Die Farbe des Balkens (blue, green, purple, red)
    
    Returns:
        str: HTML-Markup für den Fortschrittsbalken
    """
    css_class = f"progress-bar-fill-{color}"
    
    # Sicherstellen, dass der Wert im gültigen Bereich liegt
    if value < 0:
        value = 0
    elif value > 100:
        value = 100
        
    # Erstellen des DOM-Struktur für den Fortschrittsbalken
    html = f"""
    <div class="progress-bar">
        <div class="progress-bar-fill {css_class}" data-width="{value}"></div>
    </div>
    """
    
    return Markup(html) 