package ucca

import (
	"fmt"
	"strings"
	"time"
)

// =============================================================================
// License Policy Engine
// Handles license/copyright compliance for standards and norms
// =============================================================================

// LicensePolicyEngine evaluates license compliance
type LicensePolicyEngine struct {
	// Configuration can be added here
}

// NewLicensePolicyEngine creates a new license policy engine
func NewLicensePolicyEngine() *LicensePolicyEngine {
	return &LicensePolicyEngine{}
}

// Evaluate evaluates the license facts and returns the policy result
func (e *LicensePolicyEngine) Evaluate(facts *LicensedContentFacts) *LicensePolicyResult {
	result := &LicensePolicyResult{
		Allowed:       true,
		EffectiveMode: "LINK_ONLY", // Default safe mode
		Gaps:          []LicenseGap{},
		RequiredControls: []LicenseControl{},
		OutputRestrictions: &OutputRestrictions{
			AllowQuotes:     false,
			MaxQuoteLength:  0,
			RequireCitation: true,
			AllowCopy:       false,
			AllowExport:     false,
		},
		RiskScore: 0,
	}

	// If no licensed content, return early with no restrictions
	if !facts.Present {
		result.EffectiveMode = "UNRESTRICTED"
		result.OutputRestrictions = &OutputRestrictions{
			AllowQuotes:     true,
			MaxQuoteLength:  -1, // unlimited
			RequireCitation: false,
			AllowCopy:       true,
			AllowExport:     true,
		}
		return result
	}

	// Evaluate based on operation mode and license status
	switch facts.OperationMode {
	case "LINK_ONLY":
		e.evaluateLinkOnlyMode(facts, result)
	case "NOTES_ONLY":
		e.evaluateNotesOnlyMode(facts, result)
	case "EXCERPT_ONLY":
		e.evaluateExcerptOnlyMode(facts, result)
	case "FULLTEXT_RAG":
		e.evaluateFulltextRAGMode(facts, result)
	case "TRAINING":
		e.evaluateTrainingMode(facts, result)
	default:
		// Unknown mode, default to LINK_ONLY
		e.evaluateLinkOnlyMode(facts, result)
	}

	// Check publisher-specific restrictions
	e.applyPublisherRestrictions(facts, result)

	// Check distribution scope vs license type
	e.checkDistributionScope(facts, result)

	return result
}

// evaluateLinkOnlyMode - safest mode, always allowed
func (e *LicensePolicyEngine) evaluateLinkOnlyMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
	result.EffectiveMode = "LINK_ONLY"
	result.Allowed = true
	result.Reason = "Link-only Modus ist ohne spezielle Lizenz erlaubt"
	result.RiskScore = 0

	result.OutputRestrictions = &OutputRestrictions{
		AllowQuotes:     false,
		MaxQuoteLength:  0,
		RequireCitation: true,
		AllowCopy:       false,
		AllowExport:     false,
	}

	result.RequiredControls = append(result.RequiredControls, LicenseControl{
		ID:          "CTRL-LINK-ONLY-MODE",
		Title:       "Link-only / Evidence Navigator aktivieren",
		Description: "Nur Verweise und Checklisten, kein Volltext",
		WhatToDo:    "System auf LINK_ONLY konfigurieren, keine Normtexte indexieren",
		Evidence:    []string{"System-Konfiguration", "Stichproben-Audit"},
	})
}

// evaluateNotesOnlyMode - customer notes, usually allowed
func (e *LicensePolicyEngine) evaluateNotesOnlyMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
	result.EffectiveMode = "NOTES_ONLY"
	result.Allowed = true
	result.Reason = "Notes-only Modus mit kundeneigenen Zusammenfassungen"
	result.RiskScore = 10

	result.OutputRestrictions = &OutputRestrictions{
		AllowQuotes:     false, // No direct quotes from norms
		MaxQuoteLength:  0,
		RequireCitation: true,
		AllowCopy:       true, // Can copy own notes
		AllowExport:     true, // Can export own notes
	}

	result.RequiredControls = append(result.RequiredControls, LicenseControl{
		ID:          "CTRL-NOTES-ONLY-RAG",
		Title:       "Notes-only RAG (kundeneigene Paraphrasen)",
		Description: "Nur kundeneigene Zusammenfassungen indexieren",
		WhatToDo:    "UI-Flow fuer Notes-Erstellung, kein Copy/Paste von Originaltexten",
		Evidence:    []string{"Notes-Provenance-Log", "Stichproben"},
	})

	// Add gap if license type is unknown
	if facts.LicenseType == "UNKNOWN" {
		result.Gaps = append(result.Gaps, LicenseGap{
			ID:          "GAP_LICENSE_UNKNOWN",
			Title:       "Lizenzlage unklar",
			Description: "Die Lizenzlage sollte geklaert werden",
			Controls:    []string{"CTRL-LICENSE-PROOF"},
			Severity:    "WARN",
		})
		result.EscalationLevel = "E2"
	}
}

// evaluateExcerptOnlyMode - short quotes under citation rights
func (e *LicensePolicyEngine) evaluateExcerptOnlyMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
	result.EffectiveMode = "EXCERPT_ONLY"
	result.RiskScore = 30

	// Check if AI use is permitted
	if facts.AIUsePermitted == "NO" || facts.AIUsePermitted == "UNKNOWN" {
		// Downgrade to NOTES_ONLY
		result.EffectiveMode = "NOTES_ONLY"
		result.Reason = "Excerpt-Modus nicht erlaubt ohne AI-Freigabe, Downgrade auf Notes-only"
		result.Gaps = append(result.Gaps, LicenseGap{
			ID:          "GAP_AI_USE_NOT_PERMITTED",
			Title:       "AI/TDM-Nutzung nicht erlaubt",
			Description: "Zitate erfordern AI-Nutzungserlaubnis",
			Controls:    []string{"CTRL-LICENSE-PROOF", "CTRL-NOTES-ONLY-RAG"},
			Severity:    "WARN",
		})
		result.EscalationLevel = "E2"
	} else {
		result.Allowed = true
		result.Reason = "Kurze Zitate im Rahmen des Zitatrechts"
	}

	result.OutputRestrictions = &OutputRestrictions{
		AllowQuotes:     facts.AIUsePermitted == "YES",
		MaxQuoteLength:  150, // Max 150 characters per quote
		RequireCitation: true,
		AllowCopy:       false,
		AllowExport:     false,
	}

	result.RequiredControls = append(result.RequiredControls, LicenseControl{
		ID:          "CTRL-OUTPUT-GUARD-QUOTES",
		Title:       "Output-Guard: Quote-Limits",
		Description: "Zitatlänge begrenzen",
		WhatToDo:    "Max. 150 Zeichen pro Zitat, immer mit Quellenangabe",
		Evidence:    []string{"Output-Guard-Konfiguration"},
	})
}

// evaluateFulltextRAGMode - requires explicit license proof
func (e *LicensePolicyEngine) evaluateFulltextRAGMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
	result.RiskScore = 60

	if facts.AIUsePermitted == "YES" && facts.ProofUploaded {
		result.EffectiveMode = "FULLTEXT_RAG"
		result.Allowed = true
		result.Reason = "Volltext-RAG mit nachgewiesener AI-Lizenz"

		result.OutputRestrictions = &OutputRestrictions{
			AllowQuotes:     true,
			MaxQuoteLength:  500, // Still limited
			RequireCitation: true,
			AllowCopy:       false, // No copy to prevent redistribution
			AllowExport:     false, // No export
		}

		result.RequiredControls = append(result.RequiredControls,
			LicenseControl{
				ID:          "CTRL-LICENSE-GATED-INGEST",
				Title:       "License-gated Ingest",
				Description: "Technische Durchsetzung der Lizenzpruefung",
				WhatToDo:    "Ingest-Pipeline prueft Lizenz vor Indexierung",
				Evidence:    []string{"Ingest-Audit-Logs"},
			},
			LicenseControl{
				ID:          "CTRL-TENANT-ISOLATION-STANDARDS",
				Title:       "Tenant-Isolation",
				Description: "Strikte Trennung lizenzierter Inhalte",
				WhatToDo:    "Keine Cross-Tenant-Suche, kein Export",
				Evidence:    []string{"Tenant-Isolation-Dokumentation"},
			},
		)
	} else {
		// NOT ALLOWED - downgrade to LINK_ONLY
		result.Allowed = false
		result.EffectiveMode = "LINK_ONLY"
		result.Reason = "Volltext-RAG ohne Lizenznachweis nicht erlaubt"

		result.Gaps = append(result.Gaps, LicenseGap{
			ID:          "GAP_FULLTEXT_WITHOUT_PROOF",
			Title:       "Volltext-RAG ohne Lizenznachweis",
			Description: "Volltext-RAG erfordert nachgewiesene AI-Nutzungserlaubnis",
			Controls:    []string{"CTRL-LICENSE-PROOF", "CTRL-LINK-ONLY-MODE"},
			Severity:    "BLOCK",
		})

		result.EscalationLevel = "E3"

		result.StopLine = &LicenseStopLine{
			ID:      "STOP_FULLTEXT_WITHOUT_PROOF",
			Title:   "Volltext-RAG blockiert",
			Message: "Volltext-RAG erfordert einen Nachweis der AI-Nutzungserlaubnis. Bitte laden Sie den Lizenzvertrag hoch oder wechseln Sie auf Link-only Modus.",
			Outcome: "NOT_ALLOWED_UNTIL_LICENSE_CLEARED",
		}

		result.OutputRestrictions = &OutputRestrictions{
			AllowQuotes:     false,
			MaxQuoteLength:  0,
			RequireCitation: true,
			AllowCopy:       false,
			AllowExport:     false,
		}
	}
}

// evaluateTrainingMode - most restrictive, rarely allowed
func (e *LicensePolicyEngine) evaluateTrainingMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
	result.RiskScore = 80

	if facts.AIUsePermitted == "YES" && facts.ProofUploaded && facts.LicenseType == "AI_LICENSE" {
		result.EffectiveMode = "TRAINING"
		result.Allowed = true
		result.Reason = "Training mit expliziter AI-Training-Lizenz"
		result.EscalationLevel = "E3" // Still requires review
	} else {
		// HARD BLOCK
		result.Allowed = false
		result.EffectiveMode = "LINK_ONLY"
		result.Reason = "Training auf Standards ohne explizite AI-Training-Lizenz verboten"

		result.StopLine = &LicenseStopLine{
			ID:      "STOP_TRAINING_WITHOUT_PROOF",
			Title:   "Training blockiert",
			Message: "Modell-Training mit lizenzierten Standards ist ohne explizite AI-Training-Lizenz nicht zulaessig. DIN Media hat dies ausdruecklich ausgeschlossen.",
			Outcome: "NOT_ALLOWED",
		}

		result.Gaps = append(result.Gaps, LicenseGap{
			ID:          "GAP_TRAINING_ON_STANDARDS",
			Title:       "Training auf Standards verboten",
			Description: "Modell-Training erfordert explizite AI-Training-Lizenz",
			Controls:    []string{"CTRL-LICENSE-PROOF"},
			Severity:    "BLOCK",
		})

		result.EscalationLevel = "E3"
	}

	result.OutputRestrictions = &OutputRestrictions{
		AllowQuotes:     false,
		MaxQuoteLength:  0,
		RequireCitation: true,
		AllowCopy:       false,
		AllowExport:     false,
	}
}

// applyPublisherRestrictions applies publisher-specific rules
func (e *LicensePolicyEngine) applyPublisherRestrictions(facts *LicensedContentFacts, result *LicensePolicyResult) {
	if facts.Publisher == "DIN_MEDIA" {
		if facts.AIUsePermitted != "YES" {
			if facts.OperationMode == "FULLTEXT_RAG" || facts.OperationMode == "TRAINING" {
				result.Allowed = false
				result.EffectiveMode = "LINK_ONLY"

				result.StopLine = &LicenseStopLine{
					ID:      "STOP_DIN_FULLTEXT_AI_NOT_ALLOWED",
					Title:   "DIN Media AI-Nutzung blockiert",
					Message: "DIN Media untersagt die AI-Nutzung von Normen ohne explizite Genehmigung. Ein AI-Lizenzmodell ist erst ab Q4/2025 geplant. Bitte nutzen Sie Link-only oder Notes-only Modus.",
					Outcome: "NOT_ALLOWED_UNTIL_LICENSE_CLEARED",
				}

				result.Gaps = append(result.Gaps, LicenseGap{
					ID:          "GAP_DIN_MEDIA_WITHOUT_AI_LICENSE",
					Title:       "DIN Media ohne AI-Lizenz",
					Description: "DIN Media verbietet AI-Nutzung ohne explizite Genehmigung",
					Controls:    []string{"CTRL-LINK-ONLY-MODE", "CTRL-NO-CRAWLING-DIN"},
					Severity:    "BLOCK",
				})

				result.EscalationLevel = "E3"
				result.RiskScore = 70
			}
		}

		// Always add no-crawling control for DIN Media
		result.RequiredControls = append(result.RequiredControls, LicenseControl{
			ID:          "CTRL-NO-CRAWLING-DIN",
			Title:       "Crawler-Block fuer DIN Media",
			Description: "Keine automatisierten Abrufe von DIN-Normen-Portalen",
			WhatToDo:    "Domain-Denylist konfigurieren, nur manueller Import",
			Evidence:    []string{"Domain-Denylist", "Fetch-Logs"},
		})
	}
}

// checkDistributionScope checks if distribution scope matches license type
func (e *LicensePolicyEngine) checkDistributionScope(facts *LicensedContentFacts, result *LicensePolicyResult) {
	if facts.LicenseType == "SINGLE_WORKSTATION" {
		if facts.DistributionScope == "COMPANY_INTERNAL" ||
			facts.DistributionScope == "SUBSIDIARIES" ||
			facts.DistributionScope == "EXTERNAL_CUSTOMERS" {

			result.Gaps = append(result.Gaps, LicenseGap{
				ID:          "GAP_DISTRIBUTION_SCOPE_MISMATCH",
				Title:       "Verteilungsumfang uebersteigt Lizenz",
				Description: "Einzelplatz-Lizenz erlaubt keine unternehmensweite Nutzung",
				Controls:    []string{"CTRL-LICENSE-PROOF", "CTRL-LINK-ONLY-MODE"},
				Severity:    "WARN",
			})

			result.EscalationLevel = "E3"
			result.RiskScore += 20
		}
	}

	if facts.LicenseType == "NETWORK_INTRANET" {
		if facts.DistributionScope == "EXTERNAL_CUSTOMERS" {
			result.Gaps = append(result.Gaps, LicenseGap{
				ID:          "GAP_DISTRIBUTION_SCOPE_EXTERNAL",
				Title:       "Externe Verteilung mit Intranet-Lizenz",
				Description: "Intranet-Lizenz erlaubt keine externe Verteilung",
				Controls:    []string{"CTRL-LICENSE-PROOF"},
				Severity:    "WARN",
			})

			result.EscalationLevel = "E2"
			result.RiskScore += 15
		}
	}
}

// CanIngestFulltext checks if fulltext ingestion is allowed
func (e *LicensePolicyEngine) CanIngestFulltext(facts *LicensedContentFacts) bool {
	if !facts.Present {
		return true
	}

	switch facts.OperationMode {
	case "LINK_ONLY":
		return false
	case "NOTES_ONLY":
		return false
	case "EXCERPT_ONLY":
		return false
	case "FULLTEXT_RAG":
		return facts.AIUsePermitted == "YES" && facts.ProofUploaded
	case "TRAINING":
		return facts.AIUsePermitted == "YES" && facts.ProofUploaded && facts.LicenseType == "AI_LICENSE"
	default:
		return false
	}
}

// CanIngestNotes checks if customer notes can be ingested
func (e *LicensePolicyEngine) CanIngestNotes(facts *LicensedContentFacts) bool {
	if !facts.Present {
		return true
	}
	return facts.OperationMode == "NOTES_ONLY" ||
		facts.OperationMode == "EXCERPT_ONLY" ||
		facts.OperationMode == "FULLTEXT_RAG" ||
		facts.OperationMode == "TRAINING"
}

// GetEffectiveMode returns the effective operation mode after policy evaluation
func (e *LicensePolicyEngine) GetEffectiveMode(facts *LicensedContentFacts) string {
	result := e.Evaluate(facts)
	return result.EffectiveMode
}

// DecideIngest returns the ingest decision for a document
func (e *LicensePolicyEngine) DecideIngest(facts *LicensedContentFacts) *LicenseIngestDecision {
	result := e.Evaluate(facts)

	return &LicenseIngestDecision{
		AllowMetadata: true, // Metadata is always allowed
		AllowNotes:    e.CanIngestNotes(facts),
		AllowFulltext: e.CanIngestFulltext(facts),
		Reason:        result.Reason,
		EffectiveMode: result.EffectiveMode,
	}
}

// FormatAuditEntry creates an audit entry for logging
func (e *LicensePolicyEngine) FormatAuditEntry(tenantID string, documentID string, facts *LicensedContentFacts, result *LicensePolicyResult) *LicenseAuditEntry {
	decision := "ALLOW"
	if !result.Allowed {
		decision = "DENY"
	} else if result.EffectiveMode != facts.OperationMode {
		decision = "DOWNGRADE"
	}

	entry := &LicenseAuditEntry{
		Timestamp:     time.Now().UTC(),
		TenantID:      tenantID,
		DocumentID:    documentID,
		Facts:         facts,
		Decision:      decision,
		EffectiveMode: result.EffectiveMode,
		Reason:        result.Reason,
	}

	if result.StopLine != nil {
		entry.StopLineID = result.StopLine.ID
	}

	return entry
}

// FormatHumanReadableSummary creates a human-readable summary of the evaluation
func (e *LicensePolicyEngine) FormatHumanReadableSummary(result *LicensePolicyResult) string {
	var sb strings.Builder

	sb.WriteString("=== Lizenz-Policy Bewertung ===\n\n")

	if result.Allowed {
		sb.WriteString(fmt.Sprintf("Status: ERLAUBT\n"))
	} else {
		sb.WriteString(fmt.Sprintf("Status: BLOCKIERT\n"))
	}

	sb.WriteString(fmt.Sprintf("Effektiver Modus: %s\n", result.EffectiveMode))
	sb.WriteString(fmt.Sprintf("Risiko-Score: %d\n", result.RiskScore))
	sb.WriteString(fmt.Sprintf("Begruendung: %s\n\n", result.Reason))

	if result.StopLine != nil {
		sb.WriteString("!!! STOP-LINE !!!\n")
		sb.WriteString(fmt.Sprintf("  %s: %s\n", result.StopLine.ID, result.StopLine.Title))
		sb.WriteString(fmt.Sprintf("  %s\n\n", result.StopLine.Message))
	}

	if len(result.Gaps) > 0 {
		sb.WriteString("Identifizierte Luecken:\n")
		for _, gap := range result.Gaps {
			sb.WriteString(fmt.Sprintf("  - [%s] %s: %s\n", gap.Severity, gap.ID, gap.Title))
		}
		sb.WriteString("\n")
	}

	if len(result.RequiredControls) > 0 {
		sb.WriteString("Erforderliche Massnahmen:\n")
		for _, ctrl := range result.RequiredControls {
			sb.WriteString(fmt.Sprintf("  - %s: %s\n", ctrl.ID, ctrl.Title))
		}
		sb.WriteString("\n")
	}

	if result.OutputRestrictions != nil {
		sb.WriteString("Output-Einschraenkungen:\n")
		sb.WriteString(fmt.Sprintf("  Zitate erlaubt: %v\n", result.OutputRestrictions.AllowQuotes))
		sb.WriteString(fmt.Sprintf("  Max. Zitatlaenge: %d Zeichen\n", result.OutputRestrictions.MaxQuoteLength))
		sb.WriteString(fmt.Sprintf("  Copy erlaubt: %v\n", result.OutputRestrictions.AllowCopy))
		sb.WriteString(fmt.Sprintf("  Export erlaubt: %v\n", result.OutputRestrictions.AllowExport))
	}

	return sb.String()
}
