package ucca

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"time"

	"github.com/jung-kurt/gofpdf"
)

// PDFExporter generates PDF documents from obligations assessments
type PDFExporter struct {
	language string
}

// NewPDFExporter creates a new PDF exporter
func NewPDFExporter(language string) *PDFExporter {
	if language == "" {
		language = "de"
	}
	return &PDFExporter{language: language}
}

// ExportManagementMemo exports the management obligations overview as a PDF
func (e *PDFExporter) ExportManagementMemo(overview *ManagementObligationsOverview) (*ExportMemoResponse, error) {
	pdf := gofpdf.New("P", "mm", "A4", "")

	// Set UTF-8 support with DejaVu font (fallback to core fonts)
	pdf.SetFont("Helvetica", "", 12)

	// Add first page
	pdf.AddPage()

	// Add title
	e.addTitle(pdf, overview)

	// Add executive summary
	e.addExecutiveSummary(pdf, overview)

	// Add applicable regulations
	e.addApplicableRegulations(pdf, overview)

	// Add sanctions summary
	e.addSanctionsSummary(pdf, overview)

	// Add obligations table
	e.addObligationsTable(pdf, overview)

	// Add incident deadlines if present
	if len(overview.IncidentDeadlines) > 0 {
		e.addIncidentDeadlines(pdf, overview)
	}

	// Add footer with generation date
	e.addFooter(pdf, overview)

	// Generate PDF bytes
	var buf bytes.Buffer
	if err := pdf.Output(&buf); err != nil {
		return nil, fmt.Errorf("failed to generate PDF: %w", err)
	}

	// Encode as base64
	content := base64.StdEncoding.EncodeToString(buf.Bytes())

	return &ExportMemoResponse{
		Content:     content,
		ContentType: "application/pdf",
		Filename:    fmt.Sprintf("pflichten-uebersicht-%s.pdf", time.Now().Format("2006-01-02")),
		GeneratedAt: time.Now(),
	}, nil
}

// addTitle adds the document title
func (e *PDFExporter) addTitle(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	pdf.SetFont("Helvetica", "B", 24)
	pdf.SetTextColor(0, 0, 0)

	title := "Regulatorische Pflichten-Uebersicht"
	if e.language == "en" {
		title = "Regulatory Obligations Overview"
	}
	pdf.CellFormat(0, 15, title, "", 1, "C", false, 0, "")

	// Organization name
	if overview.OrganizationName != "" {
		pdf.SetFont("Helvetica", "", 14)
		pdf.CellFormat(0, 10, overview.OrganizationName, "", 1, "C", false, 0, "")
	}

	// Date
	pdf.SetFont("Helvetica", "I", 10)
	dateStr := overview.AssessmentDate.Format("02.01.2006")
	pdf.CellFormat(0, 8, fmt.Sprintf("Stand: %s", dateStr), "", 1, "C", false, 0, "")

	pdf.Ln(10)
}

// addExecutiveSummary adds the executive summary section
func (e *PDFExporter) addExecutiveSummary(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	e.addSectionHeader(pdf, "Executive Summary")

	summary := overview.ExecutiveSummary

	// Stats table
	pdf.SetFont("Helvetica", "", 11)

	stats := []struct {
		label string
		value string
	}{
		{"Anwendbare Regulierungen", fmt.Sprintf("%d", summary.TotalRegulations)},
		{"Gesamtzahl Pflichten", fmt.Sprintf("%d", summary.TotalObligations)},
		{"Kritische Pflichten", fmt.Sprintf("%d", summary.CriticalObligations)},
		{"Kommende Fristen (30 Tage)", fmt.Sprintf("%d", summary.UpcomingDeadlines)},
		{"Compliance Score", fmt.Sprintf("%d%%", summary.ComplianceScore)},
	}

	for _, stat := range stats {
		pdf.SetFont("Helvetica", "B", 11)
		pdf.CellFormat(80, 7, stat.label+":", "", 0, "L", false, 0, "")
		pdf.SetFont("Helvetica", "", 11)
		pdf.CellFormat(0, 7, stat.value, "", 1, "L", false, 0, "")
	}

	// Key risks
	if len(summary.KeyRisks) > 0 {
		pdf.Ln(5)
		pdf.SetFont("Helvetica", "B", 11)
		pdf.CellFormat(0, 7, "Wesentliche Risiken:", "", 1, "L", false, 0, "")
		pdf.SetFont("Helvetica", "", 10)
		for _, risk := range summary.KeyRisks {
			pdf.CellFormat(10, 6, "", "", 0, "L", false, 0, "")
			pdf.CellFormat(0, 6, "- "+risk, "", 1, "L", false, 0, "")
		}
	}

	// Recommended actions
	if len(summary.RecommendedActions) > 0 {
		pdf.Ln(5)
		pdf.SetFont("Helvetica", "B", 11)
		pdf.CellFormat(0, 7, "Empfohlene Massnahmen:", "", 1, "L", false, 0, "")
		pdf.SetFont("Helvetica", "", 10)
		for _, action := range summary.RecommendedActions {
			pdf.CellFormat(10, 6, "", "", 0, "L", false, 0, "")
			pdf.CellFormat(0, 6, "- "+action, "", 1, "L", false, 0, "")
		}
	}

	pdf.Ln(10)
}

// addApplicableRegulations adds the applicable regulations section
func (e *PDFExporter) addApplicableRegulations(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	e.addSectionHeader(pdf, "Anwendbare Regulierungen")

	pdf.SetFont("Helvetica", "", 10)

	// Table header
	pdf.SetFillColor(240, 240, 240)
	pdf.SetFont("Helvetica", "B", 10)
	pdf.CellFormat(60, 8, "Regulierung", "1", 0, "L", true, 0, "")
	pdf.CellFormat(50, 8, "Klassifizierung", "1", 0, "L", true, 0, "")
	pdf.CellFormat(30, 8, "Pflichten", "1", 0, "C", true, 0, "")
	pdf.CellFormat(50, 8, "Grund", "1", 1, "L", true, 0, "")

	pdf.SetFont("Helvetica", "", 10)
	for _, reg := range overview.ApplicableRegulations {
		pdf.CellFormat(60, 7, reg.Name, "1", 0, "L", false, 0, "")
		pdf.CellFormat(50, 7, truncateString(reg.Classification, 25), "1", 0, "L", false, 0, "")
		pdf.CellFormat(30, 7, fmt.Sprintf("%d", reg.ObligationCount), "1", 0, "C", false, 0, "")
		pdf.CellFormat(50, 7, truncateString(reg.Reason, 25), "1", 1, "L", false, 0, "")
	}

	pdf.Ln(10)
}

// addSanctionsSummary adds the sanctions summary section
func (e *PDFExporter) addSanctionsSummary(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	e.addSectionHeader(pdf, "Sanktionsrisiken")

	sanctions := overview.SanctionsSummary

	pdf.SetFont("Helvetica", "", 11)

	// Max financial risk
	if sanctions.MaxFinancialRisk != "" {
		pdf.SetFont("Helvetica", "B", 11)
		pdf.CellFormat(60, 7, "Max. Finanzrisiko:", "", 0, "L", false, 0, "")
		pdf.SetFont("Helvetica", "", 11)
		pdf.SetTextColor(200, 0, 0)
		pdf.CellFormat(0, 7, sanctions.MaxFinancialRisk, "", 1, "L", false, 0, "")
		pdf.SetTextColor(0, 0, 0)
	}

	// Personal liability
	pdf.SetFont("Helvetica", "B", 11)
	pdf.CellFormat(60, 7, "Persoenliche Haftung:", "", 0, "L", false, 0, "")
	pdf.SetFont("Helvetica", "", 11)
	liabilityText := "Nein"
	if sanctions.PersonalLiabilityRisk {
		liabilityText = "Ja - Geschaeftsfuehrung kann persoenlich haften"
		pdf.SetTextColor(200, 0, 0)
	}
	pdf.CellFormat(0, 7, liabilityText, "", 1, "L", false, 0, "")
	pdf.SetTextColor(0, 0, 0)

	// Criminal liability
	pdf.SetFont("Helvetica", "B", 11)
	pdf.CellFormat(60, 7, "Strafrechtliche Konsequenzen:", "", 0, "L", false, 0, "")
	pdf.SetFont("Helvetica", "", 11)
	criminalText := "Nein"
	if sanctions.CriminalLiabilityRisk {
		criminalText = "Moeglich"
		pdf.SetTextColor(200, 0, 0)
	}
	pdf.CellFormat(0, 7, criminalText, "", 1, "L", false, 0, "")
	pdf.SetTextColor(0, 0, 0)

	// Summary
	if sanctions.Summary != "" {
		pdf.Ln(3)
		pdf.SetFont("Helvetica", "I", 10)
		pdf.MultiCell(0, 5, sanctions.Summary, "", "L", false)
	}

	pdf.Ln(10)
}

// addObligationsTable adds the obligations table
func (e *PDFExporter) addObligationsTable(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	e.addSectionHeader(pdf, "Pflichten-Uebersicht")

	// Group by priority
	criticalObls := []Obligation{}
	highObls := []Obligation{}
	otherObls := []Obligation{}

	for _, obl := range overview.Obligations {
		switch obl.Priority {
		case PriorityCritical, ObligationPriority("kritisch"):
			criticalObls = append(criticalObls, obl)
		case PriorityHigh, ObligationPriority("hoch"):
			highObls = append(highObls, obl)
		default:
			otherObls = append(otherObls, obl)
		}
	}

	// Critical obligations
	if len(criticalObls) > 0 {
		pdf.SetFont("Helvetica", "B", 11)
		pdf.SetTextColor(200, 0, 0)
		pdf.CellFormat(0, 8, fmt.Sprintf("Kritische Pflichten (%d)", len(criticalObls)), "", 1, "L", false, 0, "")
		pdf.SetTextColor(0, 0, 0)
		e.addObligationsList(pdf, criticalObls)
	}

	// High priority obligations
	if len(highObls) > 0 {
		pdf.SetFont("Helvetica", "B", 11)
		pdf.SetTextColor(200, 100, 0)
		pdf.CellFormat(0, 8, fmt.Sprintf("Hohe Prioritaet (%d)", len(highObls)), "", 1, "L", false, 0, "")
		pdf.SetTextColor(0, 0, 0)
		e.addObligationsList(pdf, highObls)
	}

	// Other obligations
	if len(otherObls) > 0 {
		pdf.SetFont("Helvetica", "B", 11)
		pdf.CellFormat(0, 8, fmt.Sprintf("Weitere Pflichten (%d)", len(otherObls)), "", 1, "L", false, 0, "")
		e.addObligationsList(pdf, otherObls)
	}
}

// addObligationsList adds a list of obligations
func (e *PDFExporter) addObligationsList(pdf *gofpdf.Fpdf, obligations []Obligation) {
	// Check if we need a new page
	if pdf.GetY() > 250 {
		pdf.AddPage()
	}

	pdf.SetFont("Helvetica", "", 9)

	for _, obl := range obligations {
		// Check if we need a new page
		if pdf.GetY() > 270 {
			pdf.AddPage()
		}

		// Obligation ID and title
		pdf.SetFont("Helvetica", "B", 9)
		pdf.CellFormat(25, 5, obl.ID, "", 0, "L", false, 0, "")
		pdf.SetFont("Helvetica", "", 9)
		pdf.CellFormat(0, 5, truncateString(obl.Title, 80), "", 1, "L", false, 0, "")

		// Legal basis
		if len(obl.LegalBasis) > 0 {
			pdf.SetFont("Helvetica", "I", 8)
			pdf.CellFormat(25, 4, "", "", 0, "L", false, 0, "")
			legalText := ""
			for i, lb := range obl.LegalBasis {
				if i > 0 {
					legalText += ", "
				}
				legalText += lb.Norm
			}
			pdf.CellFormat(0, 4, truncateString(legalText, 100), "", 1, "L", false, 0, "")
		}

		// Deadline
		if obl.Deadline != nil {
			pdf.SetFont("Helvetica", "", 8)
			pdf.CellFormat(25, 4, "", "", 0, "L", false, 0, "")
			deadlineText := "Frist: "
			if obl.Deadline.Date != nil {
				deadlineText += obl.Deadline.Date.Format("02.01.2006")
			} else if obl.Deadline.Duration != "" {
				deadlineText += obl.Deadline.Duration
			} else if obl.Deadline.Interval != "" {
				deadlineText += obl.Deadline.Interval
			}
			pdf.CellFormat(0, 4, deadlineText, "", 1, "L", false, 0, "")
		}

		// Responsible
		pdf.SetFont("Helvetica", "", 8)
		pdf.CellFormat(25, 4, "", "", 0, "L", false, 0, "")
		pdf.CellFormat(0, 4, fmt.Sprintf("Verantwortlich: %s", obl.Responsible), "", 1, "L", false, 0, "")

		pdf.Ln(2)
	}

	pdf.Ln(5)
}

// addIncidentDeadlines adds the incident deadlines section
func (e *PDFExporter) addIncidentDeadlines(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	// Check if we need a new page
	if pdf.GetY() > 220 {
		pdf.AddPage()
	}

	e.addSectionHeader(pdf, "Meldepflichten bei Vorfaellen")

	pdf.SetFont("Helvetica", "", 10)

	// Group by regulation
	byRegulation := make(map[string][]IncidentDeadline)
	for _, deadline := range overview.IncidentDeadlines {
		byRegulation[deadline.RegulationID] = append(byRegulation[deadline.RegulationID], deadline)
	}

	for regID, deadlines := range byRegulation {
		pdf.SetFont("Helvetica", "B", 10)

		regName := regID
		for _, reg := range overview.ApplicableRegulations {
			if reg.ID == regID {
				regName = reg.Name
				break
			}
		}
		pdf.CellFormat(0, 7, regName, "", 1, "L", false, 0, "")

		pdf.SetFont("Helvetica", "", 9)
		for _, dl := range deadlines {
			pdf.CellFormat(40, 6, dl.Phase+":", "", 0, "L", false, 0, "")
			pdf.SetFont("Helvetica", "B", 9)
			pdf.CellFormat(30, 6, dl.Deadline, "", 0, "L", false, 0, "")
			pdf.SetFont("Helvetica", "", 9)
			pdf.CellFormat(0, 6, "an "+dl.Recipient, "", 1, "L", false, 0, "")
		}
		pdf.Ln(3)
	}

	pdf.Ln(5)
}

// addFooter adds the document footer
func (e *PDFExporter) addFooter(pdf *gofpdf.Fpdf, overview *ManagementObligationsOverview) {
	pdf.SetY(-30)
	pdf.SetFont("Helvetica", "I", 8)
	pdf.SetTextColor(128, 128, 128)

	pdf.CellFormat(0, 5, fmt.Sprintf("Generiert am %s mit BreakPilot AI Compliance SDK", time.Now().Format("02.01.2006 15:04")), "", 1, "C", false, 0, "")
	pdf.CellFormat(0, 5, "Dieses Dokument ersetzt keine rechtliche Beratung.", "", 1, "C", false, 0, "")
}

// addSectionHeader adds a section header
func (e *PDFExporter) addSectionHeader(pdf *gofpdf.Fpdf, title string) {
	pdf.SetFont("Helvetica", "B", 14)
	pdf.SetTextColor(50, 50, 50)
	pdf.CellFormat(0, 10, title, "", 1, "L", false, 0, "")
	pdf.SetTextColor(0, 0, 0)

	// Underline
	pdf.SetDrawColor(200, 200, 200)
	pdf.Line(10, pdf.GetY(), 200, pdf.GetY())
	pdf.Ln(5)
}

// truncateString truncates a string to maxLen characters
func truncateString(s string, maxLen int) string {
	if len(s) <= maxLen {
		return s
	}
	return s[:maxLen-3] + "..."
}
