"""
Report Generator for Ink Estimation Application
Generates PDF and Excel (.xlsx) client quotes and technical estimation reports.
"""

import io
from datetime import datetime
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from reportlab.lib.pagesizes import letter
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle


class ReportGenerator:
    @staticmethod
    def generate_excel(result: dict) -> bytes:
        """Creates a formatted Excel (.xlsx) workbook for the estimation."""
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "Ink Estimation Summary"
        ws.views.sheetView[0].showGridLines = True

        # Styles
        navy_fill = PatternFill(start_color="1A365D", end_color="1A365D", fill_type="solid")
        cyan_fill = PatternFill(start_color="0EA5E9", end_color="0EA5E9", fill_type="solid")
        mag_fill = PatternFill(start_color="EC4899", end_color="EC4899", fill_type="solid")
        yel_fill = PatternFill(start_color="EAB308", end_color="EAB308", fill_type="solid")
        blk_fill = PatternFill(start_color="334155", end_color="334155", fill_type="solid")
        gray_fill = PatternFill(start_color="F1F5F9", end_color="F1F5F9", fill_type="solid")

        white_bold = Font(name="Arial", size=11, bold=True, color="FFFFFF")
        dark_bold = Font(name="Arial", size=11, bold=True, color="0F172A")
        title_font = Font(name="Arial", size=16, bold=True, color="1E293B")
        sub_font = Font(name="Arial", size=10, italic=True, color="64748B")

        thin_border = Border(
            left=Side(style='thin', color='CBD5E1'),
            right=Side(style='thin', color='CBD5E1'),
            top=Side(style='thin', color='CBD5E1'),
            bottom=Side(style='thin', color='CBD5E1')
        )

        # Title Block
        ws["A1"] = "KONICA MINOLTA ACCURIOJET KM-1 — INK ESTIMATION REPORT"
        ws["A1"].font = title_font
        ws["A2"] = f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | File: {result['document']['filename']}"
        ws["A2"].font = sub_font

        # Section 1: Job Parameters
        ws["A4"] = "Job & Device Parameters"
        ws["A4"].font = dark_bold
        params = [
            ("Document Name", result["document"]["filename"]),
            ("Page Count", f"{result['document']['page_count']} pages"),
            ("Total Sheet Area", f"{result['document']['total_area_m2']} m²"),
            ("Print Mode", result["parameters"]["mode_label"]),
            ("Media / Paper", result["parameters"]["media_label"]),
            ("Quality Mode", result["parameters"]["quality_label"]),
            ("Calculation DPI", f"{result['parameters']['dpi']} DPI"),
            ("Run Quantity", f"{result['parameters']['quantity']:,} copies")
        ]
        for idx, (k, v) in enumerate(params, start=5):
            ws[f"A{idx}"] = k
            ws[f"B{idx}"] = v
            ws[f"A{idx}"].fill = gray_fill
            ws[f"A{idx}"].border = thin_border
            ws[f"B{idx}"].border = thin_border

        # Section 2: Single Copy vs Total Job Volume & Costs
        ws["D4"] = "Ink Volume & Cost Summary"
        ws["D4"].font = dark_bold

        sym = result["parameters"].get("currency_symbol", "€")
        headers = ["Channel", "Single Copy (ml)", "Single Copy (g)", "Coverage (%)", f"Job Total ({result['parameters']['quantity']:,})", f"Unit Cost ({sym}/L)", f"Total Cost ({sym})"]
        for col_num, h in enumerate(headers, start=4):
            cell = ws.cell(row=5, column=col_num, value=h)
            cell.font = white_bold
            cell.fill = navy_fill
            cell.alignment = Alignment(horizontal="center")
            cell.border = thin_border

        sc = result["single_copy_metrics"]
        cov = result["coverage_percentages"]
        jt = result["job_totals"]
        ca = result["cost_analysis"]
        cpl = result["parameters"]["cost_per_liter"]

        rows_data = [
            ("Cyan", sc["cyan_ml"], sc["cyan_grams"], f"{cov['cyan_pct']}%", f"{jt['cyan_ml']} ml", f"{sym}{cpl['cyan']}", f"{sym}{ca['cyan_cost']}", cyan_fill),
            ("Magenta", sc["magenta_ml"], sc["magenta_grams"], f"{cov['magenta_pct']}%", f"{jt['magenta_ml']} ml", f"{sym}{cpl['magenta']}", f"{sym}{ca['magenta_cost']}", mag_fill),
            ("Yellow", sc["yellow_ml"], sc["yellow_grams"], f"{cov['yellow_pct']}%", f"{jt['yellow_ml']} ml", f"{sym}{cpl['yellow']}", f"{sym}{ca['yellow_cost']}", yel_fill),
            ("Black", sc["black_ml"], sc["black_grams"], f"{cov['black_pct']}%", f"{jt['black_ml']} ml", f"{sym}{cpl['black']}", f"{sym}{ca['black_cost']}", blk_fill),
            ("TOTAL", sc["total_ml"], sc["total_grams"], f"{cov['total_tac_avg_pct']}%", f"{jt['total_ml']} ml ({jt['total_liters']} L)", "-", f"{sym}{ca['total_job_cost']}", navy_fill)
        ]

        for row_idx, r in enumerate(rows_data, start=6):
            for col_idx, val in enumerate(r[:7], start=4):
                cell = ws.cell(row=row_idx, column=col_idx, value=val)
                cell.border = thin_border
                cell.alignment = Alignment(horizontal="right" if col_idx > 4 else "left")
                if col_idx == 4:
                    cell.font = white_bold
                    cell.fill = r[7]
                    cell.alignment = Alignment(horizontal="center")
                elif row_idx == 10:
                    cell.font = dark_bold
                    cell.fill = gray_fill

        # Section 3: Per-Page Breakdown
        ws["A14"] = "Per-Page Detail Breakdown"
        ws["A14"].font = dark_bold

        p_headers = ["Page #", "Dimensions (mm)", "Cyan (ml)", "Magenta (ml)", "Yellow (ml)", "Black (ml)", "Total (ml)", "Cov C %", "Cov M %", "Cov Y %", "Cov K %"]
        for col_num, h in enumerate(p_headers, start=1):
            cell = ws.cell(row=15, column=col_num, value=h)
            cell.font = white_bold
            cell.fill = navy_fill
            cell.alignment = Alignment(horizontal="center")
            cell.border = thin_border

        for r_idx, page in enumerate(result["pages"], start=16):
            p_vals = [
                f"Page {page['page_number']}",
                f"{page['width_mm']} x {page['height_mm']}",
                page["cyan_ml"],
                page["magenta_ml"],
                page["yellow_ml"],
                page["black_ml"],
                page["total_ml"],
                f"{page['coverage_c']}%",
                f"{page['coverage_m']}%",
                f"{page['coverage_y']}%",
                f"{page['coverage_k']}%"
            ]
            for c_idx, val in enumerate(p_vals, start=1):
                cell = ws.cell(row=r_idx, column=c_idx, value=val)
                cell.border = thin_border
                cell.alignment = Alignment(horizontal="center" if c_idx <= 2 else "right")
                if r_idx % 2 == 1:
                    cell.fill = gray_fill

        # Adjust column widths
        for col in ws.columns:
            max_len = max(len(str(cell.value or '')) for cell in col)
            col_letter = openpyxl.utils.get_column_letter(col[0].column)
            ws.column_dimensions[col_letter].width = max(max_len + 3, 12)

        buf = io.BytesIO()
        wb.save(buf)
        return buf.getvalue()

    @staticmethod
    def generate_pdf(result: dict) -> bytes:
        """Creates a professional PDF Quotation / Estimation Document."""
        buf = io.BytesIO()
        doc = SimpleDocTemplate(buf, pagesize=letter, leftMargin=36, rightMargin=36, topMargin=36, bottomMargin=36)
        story = []

        styles = getSampleStyleSheet()
        title_style = ParagraphStyle(
            "DocTitle",
            parent=styles["Heading1"],
            fontSize=18,
            leading=22,
            textColor=colors.HexColor("#1A365D"),
            spaceAfter=4
        )
        subtitle_style = ParagraphStyle(
            "SubTitle",
            parent=styles["Normal"],
            fontSize=9,
            textColor=colors.HexColor("#64748B"),
            spaceAfter=12
        )
        section_style = ParagraphStyle(
            "SectionTitle",
            parent=styles["Heading2"],
            fontSize=12,
            leading=16,
            textColor=colors.HexColor("#0F172A"),
            spaceBefore=10,
            spaceAfter=6
        )

        story.append(Paragraph("KONICA MINOLTA ACCURIOJET KM-1", title_style))
        story.append(Paragraph(f"Official Ink Estimation & Quote Report | Document: {result['document']['filename']}", subtitle_style))
        story.append(HRFlowable(width="100%", thickness=1.5, color=colors.HexColor("#0EA5E9"), spaceAfter=12))

        # Job Summary Table
        p = result["parameters"]
        d = result["document"]
        sc = result["single_copy_metrics"]
        jt = result["job_totals"]
        ca = result["cost_analysis"]
        sym = result["parameters"].get("currency_symbol", "€")

        job_info_data = [
            ["File Name:", d["filename"], "Print Mode:", p["mode_label"]],
            ["Format / Pages:", f"{d['format']} ({d['page_count']} pages)", "Media / Paper:", p["media_label"]],
            ["Sheet Area:", f"{d['total_area_m2']} m²", "Quality / DPI:", f"{p['quality_label']} ({p['dpi']} DPI)"],
            ["Run Quantity:", f"{p['quantity']:,} copies", "Total Job Cost:", f"{sym}{ca['total_job_cost']:,.2f}"]
        ]
        t_info = Table(job_info_data, colWidths=[90, 180, 90, 180])
        t_info.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, -1), colors.HexColor("#F8FAFC")),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.HexColor("#1E293B")),
            ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
            ('FONTNAME', (2, 0), (2, -1), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 9),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 4),
            ('TOPPADDING', (0, 0), (-1, -1), 4),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor("#E2E8F0")),
        ]))
        story.append(t_info)
        story.append(Spacer(1, 14))

        # Volume & Cost Table
        story.append(Paragraph("Ink Consumption & Cost Breakdown", section_style))
        vol_data = [
            ["Channel", "Coverage", "1 Copy (ml)", f"Job Total ({p['quantity']:,})", "Unit Price", f"Cost ({sym})"],
            ["Cyan", f"{result['coverage_percentages']['cyan_pct']}%", f"{sc['cyan_ml']:.4f} ml", f"{jt['cyan_ml']:.2f} ml", f"{sym}{p['cost_per_liter']['cyan']:.0f}/L", f"{sym}{ca['cyan_cost']:.2f}"],
            ["Magenta", f"{result['coverage_percentages']['magenta_pct']}%", f"{sc['magenta_ml']:.4f} ml", f"{jt['magenta_ml']:.2f} ml", f"{sym}{p['cost_per_liter']['magenta']:.0f}/L", f"{sym}{ca['magenta_cost']:.2f}"],
            ["Yellow", f"{result['coverage_percentages']['yellow_pct']}%", f"{sc['yellow_ml']:.4f} ml", f"{jt['yellow_ml']:.2f} ml", f"{sym}{p['cost_per_liter']['yellow']:.0f}/L", f"{sym}{ca['yellow_cost']:.2f}"],
            ["Black", f"{result['coverage_percentages']['black_pct']}%", f"{sc['black_ml']:.4f} ml", f"{jt['black_ml']:.2f} ml", f"{sym}{p['cost_per_liter']['black']:.0f}/L", f"{sym}{ca['black_cost']:.2f}"],
            ["TOTAL", f"{result['coverage_percentages']['total_tac_avg_pct']}%", f"{sc['total_ml']:.4f} ml", f"{jt['total_liters']:.3f} L", "-", f"{sym}{ca['total_job_cost']:.2f}"]
        ]
        t_vol = Table(vol_data, colWidths=[90, 80, 90, 110, 80, 90])
        t_vol.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor("#1A365D")),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 9),
            ('ALIGN', (1, 0), (-1, -1), 'RIGHT'),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor("#CBD5E1")),
            ('BACKGROUND', (0, 1), (0, 1), colors.HexColor("#E0F2FE")),
            ('BACKGROUND', (0, 2), (0, 2), colors.HexColor("#FCE7F3")),
            ('BACKGROUND', (0, 3), (0, 3), colors.HexColor("#FEF08A")),
            ('BACKGROUND', (0, 4), (0, 4), colors.HexColor("#E2E8F0")),
            ('BACKGROUND', (0, 5), (-1, 5), colors.HexColor("#F1F5F9")),
            ('FONTNAME', (0, 5), (-1, 5), 'Helvetica-Bold'),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
            ('TOPPADDING', (0, 0), (-1, -1), 5),
        ]))
        story.append(t_vol)
        story.append(Spacer(1, 14))

        # KPI Summary box
        if d["page_count"] == 1:
            kpi_data = [
                ["Cost per Single Sheet:", f"{sym}{ca['cost_per_copy']:.4f}", "Cost per 1,000 Sheets:", f"{sym}{ca['cost_per_1000_copies']:,.2f}"]
            ]
        else:
            mode_txt = "Duplex" if p["duplex"] else "Simplex"
            kpi_data = [
                ["Cost per Copy (Full Set):", f"{sym}{ca['cost_per_copy']:.4f}", "Cost per 1,000 Copies:", f"{sym}{ca['cost_per_1000_copies']:,.2f}"],
                ["Cost per Page Side:", f"{sym}{ca['cost_per_page']:.4f}", f"Cost per {mode_txt} Sheet:", f"{sym}{ca['cost_per_sheet']:.4f}"]
            ]
        t_kpi = Table(kpi_data, colWidths=[150, 120, 150, 120])
        t_kpi.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, -1), colors.HexColor("#ECFDF5")),
            ('TEXTCOLOR', (0, 0), (-1, -1), colors.HexColor("#065F46")),
            ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
            ('FONTSIZE', (0, 0), (-1, -1), 9),
            ('GRID', (0, 0), (-1, -1), 0.5, colors.HexColor("#10B981")),
            ('ALIGN', (1, 0), (1, -1), 'LEFT'),
            ('ALIGN', (3, 0), (3, -1), 'LEFT'),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 5),
            ('TOPPADDING', (0, 0), (-1, -1), 5),
        ]))
        story.append(t_kpi)

        doc.build(story)
        return buf.getvalue()
