"""
Multi-Format-Report-Generator für das MYP-System
===============================================

Dieses Modul stellt umfassende Report-Generierung in verschiedenen Formaten bereit:
- PDF-Reports mit professionellem Layout
- Excel-Reports mit Diagrammen und Formatierungen
- CSV-Export für Datenanalyse
- JSON-Export für API-Integration
"""

import os
import io
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Union, BinaryIO
from dataclasses import dataclass, asdict
from abc import ABC, abstractmethod

# PDF-Generation
try:
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import A4, letter
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.units import inch, cm
    from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image, PageBreak
    from reportlab.graphics.shapes import Drawing
    from reportlab.graphics.charts.lineplots import LinePlot
    from reportlab.graphics.charts.barcharts import VerticalBarChart
    from reportlab.graphics.charts.piecharts import Pie
    from reportlab.lib.validators import Auto
    PDF_AVAILABLE = True
except ImportError:
    PDF_AVAILABLE = False

# Excel-Generation
try:
    import xlsxwriter
    from xlsxwriter.workbook import Workbook
    from xlsxwriter.worksheet import Worksheet
    EXCEL_AVAILABLE = True
except ImportError:
    EXCEL_AVAILABLE = False

import csv
from flask import make_response, jsonify

from utils.logging_config import get_logger
from models import Job, User, Printer, Stats, GuestRequest, get_db_session

logger = get_logger("reports")

@dataclass
class ReportConfig:
    """Konfiguration für Report-Generierung"""
    title: str
    subtitle: str = ""
    author: str = "MYP System"
    date_range: tuple = None
    include_charts: bool = True
    include_summary: bool = True
    template: str = "standard"
    logo_path: str = None
    footer_text: str = "Generiert vom MYP-System"

@dataclass
class ChartData:
    """Daten für Diagramme"""
    chart_type: str  # 'line', 'bar', 'pie'
    title: str
    data: List[Dict[str, Any]]
    labels: List[str] = None
    colors: List[str] = None

class BaseReportGenerator(ABC):
    """Abstrakte Basis-Klasse für Report-Generatoren"""
    
    def __init__(self, config: ReportConfig):
        self.config = config
        self.data = {}
        self.charts = []
    
    @abstractmethod
    def generate(self, output_stream: BinaryIO) -> bool:
        """Generiert den Report in den angegebenen Stream"""
        pass
    
    def add_data_section(self, name: str, data: List[Dict[str, Any]], headers: List[str] = None):
        """Fügt eine Datensektion hinzu"""
        self.data[name] = {
            'data': data,
            'headers': headers or (list(data[0].keys()) if data else [])
        }
    
    def add_chart(self, chart: ChartData):
        """Fügt ein Diagramm hinzu"""
        self.charts.append(chart)

class PDFReportGenerator(BaseReportGenerator):
    """PDF-Report-Generator mit professionellem Layout"""
    
    def __init__(self, config: ReportConfig):
        super().__init__(config)
        if not PDF_AVAILABLE:
            raise ImportError("ReportLab ist nicht installiert. Verwenden Sie: pip install reportlab")
        
        self.doc = None
        self.story = []
        self.styles = getSampleStyleSheet()
        self._setup_custom_styles()
    
    def _setup_custom_styles(self):
        """Richtet benutzerdefinierte Styles ein"""
        # Titel-Style
        self.styles.add(ParagraphStyle(
            name='CustomTitle',
            parent=self.styles['Heading1'],
            fontSize=24,
            spaceAfter=30,
            alignment=1,  # Zentriert
            textColor=colors.HexColor('#1f2937')
        ))
        
        # Untertitel-Style
        self.styles.add(ParagraphStyle(
            name='CustomSubtitle',
            parent=self.styles['Heading2'],
            fontSize=16,
            spaceAfter=20,
            alignment=1,
            textColor=colors.HexColor('#6b7280')
        ))
        
        # Sektions-Header
        self.styles.add(ParagraphStyle(
            name='SectionHeader',
            parent=self.styles['Heading2'],
            fontSize=14,
            spaceBefore=20,
            spaceAfter=10,
            textColor=colors.HexColor('#374151'),
            borderWidth=1,
            borderColor=colors.HexColor('#d1d5db'),
            borderPadding=5
        ))
    
    def generate(self, output_stream: BinaryIO) -> bool:
        """Generiert PDF-Report"""
        try:
            self.doc = SimpleDocTemplate(
                output_stream,
                pagesize=A4,
                rightMargin=2*cm,
                leftMargin=2*cm,
                topMargin=2*cm,
                bottomMargin=2*cm
            )
            
            self._build_header()
            self._build_summary()
            self._build_data_sections()
            self._build_charts()
            self._build_footer()
            
            self.doc.build(self.story)
            return True
            
        except Exception as e:
            logger.error(f"Fehler bei PDF-Generierung: {str(e)}")
            return False
    
    def _build_header(self):
        """Erstellt den Report-Header"""
        # Logo (falls vorhanden)
        if self.config.logo_path and os.path.exists(self.config.logo_path):
            try:
                logo = Image(self.config.logo_path, width=2*inch, height=1*inch)
                self.story.append(logo)
                self.story.append(Spacer(1, 0.2*inch))
            except Exception as e:
                logger.warning(f"Logo konnte nicht geladen werden: {str(e)}")
        
        # Titel
        title = Paragraph(self.config.title, self.styles['CustomTitle'])
        self.story.append(title)
        
        # Untertitel
        if self.config.subtitle:
            subtitle = Paragraph(self.config.subtitle, self.styles['CustomSubtitle'])
            self.story.append(subtitle)
        
        # Generierungsdatum
        date_text = f"Generiert am: {datetime.now().strftime('%d.%m.%Y %H:%M')}"
        date_para = Paragraph(date_text, self.styles['Normal'])
        self.story.append(date_para)
        
        # Autor
        author_text = f"Erstellt von: {self.config.author}"
        author_para = Paragraph(author_text, self.styles['Normal'])
        self.story.append(author_para)
        
        self.story.append(Spacer(1, 0.3*inch))
    
    def _build_summary(self):
        """Erstellt die Zusammenfassung"""
        if not self.config.include_summary:
            return
        
        header = Paragraph("Zusammenfassung", self.styles['SectionHeader'])
        self.story.append(header)
        
        # Sammle Statistiken aus den Daten
        total_records = sum(len(section['data']) for section in self.data.values())
        
        summary_data = [
            ['Gesamtanzahl Datensätze', str(total_records)],
            ['Berichtszeitraum', self._format_date_range()],
            ['Anzahl Sektionen', str(len(self.data))],
            ['Anzahl Diagramme', str(len(self.charts))]
        ]
        
        summary_table = Table(summary_data, colWidths=[4*inch, 2*inch])
        summary_table.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#f3f4f6')),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.black),
            ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, 0), 12),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            ('BACKGROUND', (0, 1), (-1, -1), colors.white),
            ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#d1d5db'))
        ]))
        
        self.story.append(summary_table)
        self.story.append(Spacer(1, 0.2*inch))
    
    def _build_data_sections(self):
        """Erstellt die Datensektionen"""
        for section_name, section_data in self.data.items():
            # Sektions-Header
            header = Paragraph(section_name, self.styles['SectionHeader'])
            self.story.append(header)
            
            # Daten-Tabelle
            table_data = [section_data['headers']]
            table_data.extend([
                [str(row.get(header, '')) for header in section_data['headers']]
                for row in section_data['data']
            ])
            
            # Spaltenbreiten berechnen
            col_count = len(section_data['headers'])
            col_width = (self.doc.width - 2*inch) / col_count
            col_widths = [col_width] * col_count
            
            table = Table(table_data, colWidths=col_widths, repeatRows=1)
            table.setStyle(TableStyle([
                # Header-Styling
                ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#3b82f6')),
                ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
                ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
                ('FONTSIZE', (0, 0), (-1, 0), 10),
                
                # Daten-Styling
                ('FONTNAME', (0, 1), (-1, -1), 'Helvetica'),
                ('FONTSIZE', (0, 1), (-1, -1), 9),
                ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#f9fafb')]),
                
                # Rahmen
                ('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor('#d1d5db')),
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                ('LEFTPADDING', (0, 0), (-1, -1), 6),
                ('RIGHTPADDING', (0, 0), (-1, -1), 6),
                ('TOPPADDING', (0, 0), (-1, -1), 8),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 8),
            ]))
            
            self.story.append(table)
            self.story.append(Spacer(1, 0.2*inch))
            
            # Seitenumbruch bei vielen Daten
            if len(section_data['data']) > 20:
                self.story.append(PageBreak())
    
    def _build_charts(self):
        """Erstellt die Diagramme"""
        if not self.config.include_charts or not self.charts:
            return
        
        header = Paragraph("Diagramme", self.styles['SectionHeader'])
        self.story.append(header)
        
        for chart in self.charts:
            chart_title = Paragraph(chart.title, self.styles['Heading3'])
            self.story.append(chart_title)
            
            # Diagramm basierend auf Typ erstellen
            drawing = self._create_chart_drawing(chart)
            if drawing:
                self.story.append(drawing)
                self.story.append(Spacer(1, 0.2*inch))
    
    def _create_chart_drawing(self, chart: ChartData) -> Optional[Any]:
        """Erstellt ein Diagramm-Drawing"""
        # Überprüfe ob PDF-Bibliotheken verfügbar sind
        if not PDF_AVAILABLE:
            logger.warning("PDF-Bibliotheken nicht verfügbar - Diagramm wird übersprungen")
            return None
            
        try:
            drawing = Drawing(400, 300)
            
            if chart.chart_type == 'bar':
                bar_chart = VerticalBarChart()
                bar_chart.x = 50
                bar_chart.y = 50
                bar_chart.height = 200
                bar_chart.width = 300
                
                # Daten vorbereiten
                values = [[item.get('value', 0) for item in chart.data]]
                categories = [item.get('label', f'Item {i}') for i, item in enumerate(chart.data)]
                
                bar_chart.data = values
                bar_chart.categoryAxis.categoryNames = categories
                bar_chart.valueAxis.valueMin = 0
                
                # Farben setzen
                if chart.colors:
                    bar_chart.bars[0].fillColor = colors.HexColor(chart.colors[0] if chart.colors else '#3b82f6')
                
                drawing.add(bar_chart)
            
            elif chart.chart_type == 'pie':
                pie_chart = Pie()
                pie_chart.x = 150
                pie_chart.y = 100
                pie_chart.width = 100
                pie_chart.height = 100
                
                # Daten vorbereiten
                pie_chart.data = [item.get('value', 0) for item in chart.data]
                pie_chart.labels = [item.get('label', f'Item {i}') for i, item in enumerate(chart.data)]
                
                # Farben setzen
                if chart.colors:
                    pie_chart.slices.fillColor = colors.HexColor(chart.colors[0] if chart.colors else '#3b82f6')
                
                drawing.add(pie_chart)
            
            return drawing
            
        except Exception as e:
            logger.error(f"Fehler bei Diagramm-Erstellung: {str(e)}")
            return None
    
    def _build_footer(self):
        """Erstellt den Report-Footer"""
        footer_text = self.config.footer_text
        footer = Paragraph(footer_text, self.styles['Normal'])
        self.story.append(Spacer(1, 0.3*inch))
        self.story.append(footer)
    
    def _format_date_range(self) -> str:
        """Formatiert den Datumsbereich"""
        if not self.config.date_range:
            return "Alle verfügbaren Daten"
        
        start_date, end_date = self.config.date_range
        return f"{start_date.strftime('%d.%m.%Y')} - {end_date.strftime('%d.%m.%Y')}"

class ExcelReportGenerator(BaseReportGenerator):
    """Excel-Report-Generator mit Diagrammen und Formatierungen"""
    
    def __init__(self, config: ReportConfig):
        super().__init__(config)
        if not EXCEL_AVAILABLE:
            raise ImportError("XlsxWriter ist nicht installiert. Verwenden Sie: pip install xlsxwriter")
        
        self.workbook = None
        self.formats = {}
    
    def generate(self, output_stream: BinaryIO) -> bool:
        """Generiert Excel-Report"""
        try:
            self.workbook = xlsxwriter.Workbook(output_stream, {'in_memory': True})
            self._setup_formats()
            
            # Zusammenfassungs-Arbeitsblatt
            if self.config.include_summary:
                self._create_summary_worksheet()
            
            # Daten-Arbeitsblätter
            for section_name, section_data in self.data.items():
                self._create_data_worksheet(section_name, section_data)
            
            # Diagramm-Arbeitsblätter
            if self.config.include_charts and self.charts:
                self._create_charts_worksheet()
            
            self.workbook.close()
            return True
            
        except Exception as e:
            logger.error(f"Fehler bei Excel-Generierung: {str(e)}")
            return False
    
    def _setup_formats(self):
        """Richtet Excel-Formate ein"""
        self.formats = {
            'title': self.workbook.add_format({
                'font_size': 18,
                'bold': True,
                'align': 'center',
                'bg_color': '#1f2937',
                'font_color': 'white',
                'border': 1
            }),
            'header': self.workbook.add_format({
                'font_size': 12,
                'bold': True,
                'bg_color': '#3b82f6',
                'font_color': 'white',
                'align': 'center',
                'border': 1
            }),
            'data': self.workbook.add_format({
                'align': 'center',
                'border': 1
            }),
            'data_alt': self.workbook.add_format({
                'align': 'center',
                'bg_color': '#f9fafb',
                'border': 1
            }),
            'number': self.workbook.add_format({
                'num_format': '#,##0',
                'align': 'right',
                'border': 1
            }),
            'currency': self.workbook.add_format({
                'num_format': '#,##0.00 €',
                'align': 'right',
                'border': 1
            }),
            'percentage': self.workbook.add_format({
                'num_format': '0.00%',
                'align': 'right',
                'border': 1
            }),
            'date': self.workbook.add_format({
                'num_format': 'dd.mm.yyyy',
                'align': 'center',
                'border': 1
            })
        }
    
    def _create_summary_worksheet(self):
        """Erstellt das Zusammenfassungs-Arbeitsblatt"""
        worksheet = self.workbook.add_worksheet('Zusammenfassung')
        
        # Titel
        worksheet.merge_range('A1:E1', self.config.title, self.formats['title'])
        
        # Untertitel
        if self.config.subtitle:
            worksheet.merge_range('A2:E2', self.config.subtitle, self.formats['header'])
        
        # Metadaten
        row = 4
        metadata = [
            ['Generiert am:', datetime.now().strftime('%d.%m.%Y %H:%M')],
            ['Erstellt von:', self.config.author],
            ['Berichtszeitraum:', self._format_date_range()],
            ['Anzahl Sektionen:', str(len(self.data))],
            ['Anzahl Diagramme:', str(len(self.charts))]
        ]
        
        for label, value in metadata:
            worksheet.write(row, 0, label, self.formats['header'])
            worksheet.write(row, 1, value, self.formats['data'])
            row += 1
        
        # Statistiken pro Sektion
        row += 2
        worksheet.write(row, 0, 'Sektions-Übersicht:', self.formats['header'])
        row += 1
        
        for section_name, section_data in self.data.items():
            worksheet.write(row, 0, section_name, self.formats['data'])
            worksheet.write(row, 1, len(section_data['data']), self.formats['number'])
            row += 1
        
        # Spaltenbreiten anpassen
        worksheet.set_column('A:A', 25)
        worksheet.set_column('B:B', 20)
    
    def _create_data_worksheet(self, section_name: str, section_data: Dict[str, Any]):
        """Erstellt ein Daten-Arbeitsblatt"""
        # Ungültige Zeichen für Arbeitsblatt-Namen ersetzen
        safe_name = ''.join(c for c in section_name if c.isalnum() or c in ' -_')[:31]
        worksheet = self.workbook.add_worksheet(safe_name)
        
        # Header schreiben
        headers = section_data['headers']
        for col, header in enumerate(headers):
            worksheet.write(0, col, header, self.formats['header'])
        
        # Daten schreiben
        for row_idx, row_data in enumerate(section_data['data'], start=1):
            for col_idx, header in enumerate(headers):
                value = row_data.get(header, '')
                
                # Format basierend auf Datentyp wählen
                cell_format = self._get_cell_format(value, row_idx)
                worksheet.write(row_idx, col_idx, value, cell_format)
        
        # Autofilter hinzufügen
        if section_data['data']:
            worksheet.autofilter(0, 0, len(section_data['data']), len(headers) - 1)
        
        # Spaltenbreiten anpassen
        for col_idx, header in enumerate(headers):
            max_length = max(
                len(str(header)),
                max(len(str(row.get(header, ''))) for row in section_data['data']) if section_data['data'] else 0
            )
            worksheet.set_column(col_idx, col_idx, min(max_length + 2, 50))
    
    def _create_charts_worksheet(self):
        """Erstellt das Diagramm-Arbeitsblatt"""
        worksheet = self.workbook.add_worksheet('Diagramme')
        
        row = 0
        for chart_idx, chart_data in enumerate(self.charts):
            # Diagramm-Titel
            worksheet.write(row, 0, chart_data.title, self.formats['header'])
            row += 2
            
            # Daten für Diagramm vorbereiten
            data_worksheet_name = f'Chart_Data_{chart_idx}'
            data_worksheet = self.workbook.add_worksheet(data_worksheet_name)
            
            # Daten ins Data-Arbeitsblatt schreiben
            labels = [item.get('label', f'Item {i}') for i, item in enumerate(chart_data.data)]
            values = [item.get('value', 0) for item in chart_data.data]
            
            data_worksheet.write_column('A1', ['Label'] + labels)
            data_worksheet.write_column('B1', ['Value'] + values)
            
            # Excel-Diagramm erstellen
            if chart_data.chart_type == 'bar':
                chart = self.workbook.add_chart({'type': 'column'})
            elif chart_data.chart_type == 'line':
                chart = self.workbook.add_chart({'type': 'line'})
            elif chart_data.chart_type == 'pie':
                chart = self.workbook.add_chart({'type': 'pie'})
            else:
                chart = self.workbook.add_chart({'type': 'column'})
            
            # Datenreihe hinzufügen
            chart.add_series({
                'name': chart_data.title,
                'categories': [data_worksheet_name, 1, 0, len(labels), 0],
                'values': [data_worksheet_name, 1, 1, len(values), 1],
            })
            
            chart.set_title({'name': chart_data.title})
            chart.set_x_axis({'name': 'Kategorien'})
            chart.set_y_axis({'name': 'Werte'})
            
            # Diagramm ins Arbeitsblatt einfügen
            worksheet.insert_chart(row, 0, chart)
            row += 15  # Platz für nächstes Diagramm
    
    def _get_cell_format(self, value: Any, row_idx: int):
        """Bestimmt das Zellformat basierend auf dem Wert"""
        # Alternierende Zeilenfarben
        base_format = self.formats['data'] if row_idx % 2 == 1 else self.formats['data_alt']
        
        # Spezielle Formate für Zahlen, Daten, etc.
        if isinstance(value, (int, float)):
            return self.formats['number']
        elif isinstance(value, datetime):
            return self.formats['date']
        elif isinstance(value, str) and value.endswith('%'):
            return self.formats['percentage']
        elif isinstance(value, str) and '€' in value:
            return self.formats['currency']
        
        return base_format
    
    def _format_date_range(self) -> str:
        """Formatiert den Datumsbereich"""
        if not self.config.date_range:
            return "Alle verfügbaren Daten"
        
        start_date, end_date = self.config.date_range
        return f"{start_date.strftime('%d.%m.%Y')} - {end_date.strftime('%d.%m.%Y')}"

class CSVReportGenerator(BaseReportGenerator):
    """CSV-Report-Generator für Datenanalyse"""
    
    def generate(self, output_stream: BinaryIO) -> bool:
        """Generiert CSV-Report"""
        try:
            # Text-Stream für CSV-Writer
            text_stream = io.TextIOWrapper(output_stream, encoding='utf-8-sig', newline='')
            writer = csv.writer(text_stream, delimiter=';', quoting=csv.QUOTE_MINIMAL)
            
            # Header mit Metadaten
            writer.writerow([f'# {self.config.title}'])
            writer.writerow([f'# Generiert am: {datetime.now().strftime("%d.%m.%Y %H:%M")}'])
            writer.writerow([f'# Erstellt von: {self.config.author}'])
            writer.writerow([''])  # Leerzeile
            
            # Daten-Sektionen
            for section_name, section_data in self.data.items():
                writer.writerow([f'# Sektion: {section_name}'])
                
                # Headers
                writer.writerow(section_data['headers'])
                
                # Daten
                for row in section_data['data']:
                    csv_row = [str(row.get(header, '')) for header in section_data['headers']]
                    writer.writerow(csv_row)
                
                writer.writerow([''])  # Leerzeile zwischen Sektionen
            
            text_stream.flush()
            return True
            
        except Exception as e:
            logger.error(f"Fehler bei CSV-Generierung: {str(e)}")
            return False

class JSONReportGenerator(BaseReportGenerator):
    """JSON-Report-Generator für API-Integration"""
    
    def generate(self, output_stream: BinaryIO) -> bool:
        """Generiert JSON-Report"""
        try:
            report_data = {
                'metadata': {
                    'title': self.config.title,
                    'subtitle': self.config.subtitle,
                    'author': self.config.author,
                    'generated_at': datetime.now().isoformat(),
                    'date_range': {
                        'start': self.config.date_range[0].isoformat() if self.config.date_range else None,
                        'end': self.config.date_range[1].isoformat() if self.config.date_range else None
                    } if self.config.date_range else None
                },
                'data': self.data,
                'charts': [asdict(chart) for chart in self.charts] if self.charts else []
            }
            
            json_str = json.dumps(report_data, ensure_ascii=False, indent=2, default=str)
            output_stream.write(json_str.encode('utf-8'))
            return True
            
        except Exception as e:
            logger.error(f"Fehler bei JSON-Generierung: {str(e)}")
            return False

class ReportFactory:
    """Factory für Report-Generatoren"""
    
    GENERATORS = {
        'pdf': PDFReportGenerator,
        'excel': ExcelReportGenerator,
        'xlsx': ExcelReportGenerator,
        'csv': CSVReportGenerator,
        'json': JSONReportGenerator
    }
    
    @classmethod
    def create_generator(cls, format_type: str, config: ReportConfig) -> BaseReportGenerator:
        """Erstellt einen Report-Generator für das angegebene Format"""
        format_type = format_type.lower()
        
        if format_type not in cls.GENERATORS:
            raise ValueError(f"Unbekanntes Report-Format: {format_type}")
        
        generator_class = cls.GENERATORS[format_type]
        return generator_class(config)
    
    @classmethod
    def get_available_formats(cls) -> List[str]:
        """Gibt verfügbare Report-Formate zurück"""
        available = []
        
        for format_type, generator_class in cls.GENERATORS.items():
            try:
                # Test ob Generator funktioniert
                if format_type in ['pdf'] and not PDF_AVAILABLE:
                    continue
                elif format_type in ['excel', 'xlsx'] and not EXCEL_AVAILABLE:
                    continue
                
                available.append(format_type)
            except ImportError:
                continue
        
        return available

# Vordefinierte Report-Templates
class JobReportBuilder:
    """Builder für Job-Reports"""
    
    @staticmethod
    def build_jobs_report(
        start_date: datetime = None,
        end_date: datetime = None,
        user_id: int = None,
        printer_id: int = None,
        include_completed: bool = True,
        include_cancelled: bool = False
    ) -> Dict[str, Any]:
        """Erstellt Job-Report-Daten"""
        
        with get_db_session() as db_session:
            query = db_session.query(Job)
            
            # Filter anwenden
            if start_date:
                query = query.filter(Job.created_at >= start_date)
            if end_date:
                query = query.filter(Job.created_at <= end_date)
            if user_id:
                query = query.filter(Job.user_id == user_id)
            if printer_id:
                query = query.filter(Job.printer_id == printer_id)
            
            status_filters = []
            if include_completed:
                status_filters.append('finished')
            if include_cancelled:
                status_filters.append('cancelled')
            if not include_cancelled and not include_completed:
                status_filters = ['scheduled', 'running', 'paused']
            
            if status_filters:
                query = query.filter(Job.status.in_(status_filters))
            
            jobs = query.all()
            
            # Daten vorbereiten
            job_data = []
            for job in jobs:
                job_data.append({
                    'ID': job.id,
                    'Name': job.name,
                    'Benutzer': job.user.name if job.user else 'Unbekannt',
                    'Drucker': job.printer.name if job.printer else 'Unbekannt',
                    'Status': job.status,
                    'Erstellt': job.created_at.strftime('%d.%m.%Y %H:%M') if job.created_at else '',
                    'Gestartet': job.start_at.strftime('%d.%m.%Y %H:%M') if job.start_at else '',
                    'Beendet': job.end_at.strftime('%d.%m.%Y %H:%M') if job.end_at else '',
                    'Dauer (Min)': job.duration_minutes or 0,
                    'Material (g)': job.material_used or 0,
                    'Beschreibung': job.description or ''
                })
            
            return {
                'data': job_data,
                'headers': ['ID', 'Name', 'Benutzer', 'Drucker', 'Status', 'Erstellt', 'Gestartet', 'Beendet', 'Dauer (Min)', 'Material (g)', 'Beschreibung']
            }

class UserReportBuilder:
    """Builder für Benutzer-Reports"""
    
    @staticmethod
    def build_users_report(include_inactive: bool = False) -> Dict[str, Any]:
        """Erstellt Benutzer-Report-Daten"""
        
        with get_db_session() as db_session:
            query = db_session.query(User)
            
            if not include_inactive:
                query = query.filter(User.active == True)
            
            users = query.all()
            
            # Daten vorbereiten
            user_data = []
            for user in users:
                user_data.append({
                    'ID': user.id,
                    'Name': user.name,
                    'E-Mail': user.email,
                    'Benutzername': user.username,
                    'Rolle': user.role,
                    'Aktiv': 'Ja' if user.active else 'Nein',
                    'Abteilung': user.department or '',
                    'Position': user.position or '',
                    'Erstellt': user.created_at.strftime('%d.%m.%Y') if user.created_at else '',
                    'Letzter Login': user.last_login.strftime('%d.%m.%Y %H:%M') if user.last_login else 'Nie'
                })
            
            return {
                'data': user_data,
                'headers': ['ID', 'Name', 'E-Mail', 'Benutzername', 'Rolle', 'Aktiv', 'Abteilung', 'Position', 'Erstellt', 'Letzter Login']
            }

class PrinterReportBuilder:
    """Builder für Drucker-Reports"""
    
    @staticmethod
    def build_printers_report(include_inactive: bool = False) -> Dict[str, Any]:
        """Erstellt Drucker-Report-Daten"""
        
        with get_db_session() as db_session:
            query = db_session.query(Printer)
            
            if not include_inactive:
                query = query.filter(Printer.active == True)
            
            printers = query.all()
            
            # Daten vorbereiten
            printer_data = []
            for printer in printers:
                printer_data.append({
                    'ID': printer.id,
                    'Name': printer.name,
                    'Modell': printer.model or '',
                    'Standort': printer.location or '',
                    'IP-Adresse': printer.ip_address or '',
                    'MAC-Adresse': printer.mac_address,
                    'Plug-IP': printer.plug_ip,
                    'Status': printer.status,
                    'Aktiv': 'Ja' if printer.active else 'Nein',
                    'Erstellt': printer.created_at.strftime('%d.%m.%Y') if printer.created_at else '',
                    'Letzte Prüfung': printer.last_checked.strftime('%d.%m.%Y %H:%M') if printer.last_checked else 'Nie'
                })
            
            return {
                'data': printer_data,
                'headers': ['ID', 'Name', 'Modell', 'Standort', 'IP-Adresse', 'MAC-Adresse', 'Plug-IP', 'Status', 'Aktiv', 'Erstellt', 'Letzte Prüfung']
            }

def generate_comprehensive_report(
    format_type: str,
    start_date: datetime = None,
    end_date: datetime = None,
    include_jobs: bool = True,
    include_users: bool = True,
    include_printers: bool = True,
    user_id: int = None
) -> bytes:
    """Generiert einen umfassenden System-Report"""
    
    # Konfiguration
    config = ReportConfig(
        title="MYP System Report",
        subtitle="Umfassende Systemübersicht",
        author="MYP System",
        date_range=(start_date, end_date) if start_date and end_date else None,
        include_charts=True,
        include_summary=True
    )
    
    # Generator erstellen
    generator = ReportFactory.create_generator(format_type, config)
    
    # Daten hinzufügen
    if include_jobs:
        job_data = JobReportBuilder.build_jobs_report(
            start_date=start_date,
            end_date=end_date,
            user_id=user_id
        )
        generator.add_data_section("Jobs", job_data['data'], job_data['headers'])
        
        # Job-Status-Diagramm
        status_counts = {}
        for job in job_data['data']:
            status = job['Status']
            status_counts[status] = status_counts.get(status, 0) + 1
        
        chart_data = ChartData(
            chart_type='pie',
            title='Job-Status-Verteilung',
            data=[{'label': status, 'value': count} for status, count in status_counts.items()]
        )
        generator.add_chart(chart_data)
    
    if include_users:
        user_data = UserReportBuilder.build_users_report()
        generator.add_data_section("Benutzer", user_data['data'], user_data['headers'])
    
    if include_printers:
        printer_data = PrinterReportBuilder.build_printers_report()
        generator.add_data_section("Drucker", printer_data['data'], printer_data['headers'])
    
    # Report generieren
    output = io.BytesIO()
    success = generator.generate(output)
    
    if success:
        output.seek(0)
        return output.getvalue()
    else:
        raise Exception("Report-Generierung fehlgeschlagen")

# Zusätzliche Abhängigkeiten zu requirements.txt hinzufügen
ADDITIONAL_REQUIREMENTS = [
    "reportlab>=4.0.0",
    "xlsxwriter>=3.0.0"
] 