// Package policy provides whitelist-based data source management for the edu-search-service.
// It implements source policies, operation permissions, PII detection, and audit logging
// for compliance with German data protection regulations.
package policy

import (
	"encoding/json"
	"time"

	"github.com/google/uuid"
)

// =============================================================================
// ENUMS AND CONSTANTS
// =============================================================================

// Bundesland represents German federal states (2-letter codes).
type Bundesland string

const (
	BundeslandBW Bundesland = "BW" // Baden-Wuerttemberg
	BundeslandBY Bundesland = "BY" // Bayern
	BundeslandBE Bundesland = "BE" // Berlin
	BundeslandBB Bundesland = "BB" // Brandenburg
	BundeslandHB Bundesland = "HB" // Bremen
	BundeslandHH Bundesland = "HH" // Hamburg
	BundeslandHE Bundesland = "HE" // Hessen
	BundeslandMV Bundesland = "MV" // Mecklenburg-Vorpommern
	BundeslandNI Bundesland = "NI" // Niedersachsen
	BundeslandNW Bundesland = "NW" // Nordrhein-Westfalen
	BundeslandRP Bundesland = "RP" // Rheinland-Pfalz
	BundeslandSL Bundesland = "SL" // Saarland
	BundeslandSN Bundesland = "SN" // Sachsen
	BundeslandST Bundesland = "ST" // Sachsen-Anhalt
	BundeslandSH Bundesland = "SH" // Schleswig-Holstein
	BundeslandTH Bundesland = "TH" // Thueringen
)

// ValidBundeslaender contains all valid German federal state codes.
var ValidBundeslaender = []Bundesland{
	BundeslandBW, BundeslandBY, BundeslandBE, BundeslandBB,
	BundeslandHB, BundeslandHH, BundeslandHE, BundeslandMV,
	BundeslandNI, BundeslandNW, BundeslandRP, BundeslandSL,
	BundeslandSN, BundeslandST, BundeslandSH, BundeslandTH,
}

// License represents allowed license types for data sources.
type License string

const (
	LicenseDLDEBY20  License = "DL-DE-BY-2.0" // Datenlizenz Deutschland - Namensnennung
	LicenseCCBY      License = "CC-BY"        // Creative Commons Attribution
	LicenseCCBYSA    License = "CC-BY-SA"     // Creative Commons Attribution-ShareAlike
	LicenseCCBYNC    License = "CC-BY-NC"     // Creative Commons Attribution-NonCommercial
	LicenseCCBYNCSA  License = "CC-BY-NC-SA"  // Creative Commons Attribution-NonCommercial-ShareAlike
	LicenseCC0       License = "CC0"          // Public Domain
	LicenseParagraph5 License = "§5 UrhG"     // Amtliche Werke (German Copyright Act)
	LicenseCustom    License = "Custom"       // Custom license (requires legal basis)
)

// Operation represents the types of operations that can be performed on data.
type Operation string

const (
	OperationLookup   Operation = "lookup"   // Display/Search
	OperationRAG      Operation = "rag"      // RAG (Retrieval-Augmented Generation)
	OperationTraining Operation = "training" // Model Training (VERBOTEN by default)
	OperationExport   Operation = "export"   // Data Export
)

// ValidOperations contains all valid operation types.
var ValidOperations = []Operation{
	OperationLookup,
	OperationRAG,
	OperationTraining,
	OperationExport,
}

// PIIRuleType represents the type of PII detection rule.
type PIIRuleType string

const (
	PIIRuleTypeRegex   PIIRuleType = "regex"   // Regular expression pattern
	PIIRuleTypeKeyword PIIRuleType = "keyword" // Keyword matching
)

// PIISeverity represents the severity level of a PII match.
type PIISeverity string

const (
	PIISeverityBlock  PIISeverity = "block"  // Block content completely
	PIISeverityWarn   PIISeverity = "warn"   // Warn but allow
	PIISeverityRedact PIISeverity = "redact" // Redact matched content
)

// AuditAction represents the type of action logged in the audit trail.
type AuditAction string

const (
	AuditActionCreate     AuditAction = "create"
	AuditActionUpdate     AuditAction = "update"
	AuditActionDelete     AuditAction = "delete"
	AuditActionActivate   AuditAction = "activate"
	AuditActionDeactivate AuditAction = "deactivate"
	AuditActionApprove    AuditAction = "approve"
)

// AuditEntityType represents the type of entity being audited.
type AuditEntityType string

const (
	AuditEntitySourcePolicy        AuditEntityType = "source_policy"
	AuditEntityAllowedSource       AuditEntityType = "allowed_source"
	AuditEntityOperationPermission AuditEntityType = "operation_permission"
	AuditEntityPIIRule             AuditEntityType = "pii_rule"
)

// BlockReason represents the reason why content was blocked.
type BlockReason string

const (
	BlockReasonNotWhitelisted    BlockReason = "not_whitelisted"
	BlockReasonPIIDetected       BlockReason = "pii_detected"
	BlockReasonTrainingForbidden BlockReason = "training_forbidden"
	BlockReasonLicenseViolation  BlockReason = "license_violation"
	BlockReasonManualBlock       BlockReason = "manual_block"
)

// =============================================================================
// CORE MODELS
// =============================================================================

// SourcePolicy represents a versioned policy for data source management.
// Policies can be scoped to a specific Bundesland or apply federally (bundesland = nil).
type SourcePolicy struct {
	ID          uuid.UUID   `json:"id" db:"id"`
	Version     int         `json:"version" db:"version"`
	Name        string      `json:"name" db:"name"`
	Description *string     `json:"description,omitempty" db:"description"`
	Bundesland  *Bundesland `json:"bundesland,omitempty" db:"bundesland"`
	IsActive    bool        `json:"is_active" db:"is_active"`
	CreatedAt   time.Time   `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time   `json:"updated_at" db:"updated_at"`
	ApprovedBy  *uuid.UUID  `json:"approved_by,omitempty" db:"approved_by"`
	ApprovedAt  *time.Time  `json:"approved_at,omitempty" db:"approved_at"`

	// Joined fields (populated by queries)
	Sources []AllowedSource `json:"sources,omitempty"`
}

// AllowedSource represents a whitelisted data source with license information.
type AllowedSource struct {
	ID               uuid.UUID `json:"id" db:"id"`
	PolicyID         uuid.UUID `json:"policy_id" db:"policy_id"`
	Domain           string    `json:"domain" db:"domain"`
	Name             string    `json:"name" db:"name"`
	Description      *string   `json:"description,omitempty" db:"description"`
	License          License   `json:"license" db:"license"`
	LegalBasis       *string   `json:"legal_basis,omitempty" db:"legal_basis"`
	CitationTemplate *string   `json:"citation_template,omitempty" db:"citation_template"`
	TrustBoost       float64   `json:"trust_boost" db:"trust_boost"`
	IsActive         bool      `json:"is_active" db:"is_active"`
	CreatedAt        time.Time `json:"created_at" db:"created_at"`
	UpdatedAt        time.Time `json:"updated_at" db:"updated_at"`

	// Joined fields (populated by queries)
	Operations []OperationPermission `json:"operations,omitempty"`
	PolicyName *string               `json:"policy_name,omitempty"`
}

// OperationPermission represents the permission matrix for a specific source.
type OperationPermission struct {
	ID               uuid.UUID `json:"id" db:"id"`
	SourceID         uuid.UUID `json:"source_id" db:"source_id"`
	Operation        Operation `json:"operation" db:"operation"`
	IsAllowed        bool      `json:"is_allowed" db:"is_allowed"`
	RequiresCitation bool      `json:"requires_citation" db:"requires_citation"`
	Notes            *string   `json:"notes,omitempty" db:"notes"`
	CreatedAt        time.Time `json:"created_at" db:"created_at"`
	UpdatedAt        time.Time `json:"updated_at" db:"updated_at"`
}

// PIIRule represents a rule for detecting personally identifiable information.
type PIIRule struct {
	ID          uuid.UUID   `json:"id" db:"id"`
	Name        string      `json:"name" db:"name"`
	Description *string     `json:"description,omitempty" db:"description"`
	RuleType    PIIRuleType `json:"rule_type" db:"rule_type"`
	Pattern     string      `json:"pattern" db:"pattern"`
	Severity    PIISeverity `json:"severity" db:"severity"`
	IsActive    bool        `json:"is_active" db:"is_active"`
	CreatedAt   time.Time   `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time   `json:"updated_at" db:"updated_at"`
}

// =============================================================================
// AUDIT AND LOGGING MODELS
// =============================================================================

// PolicyAuditLog represents an immutable audit log entry for policy changes.
type PolicyAuditLog struct {
	ID         uuid.UUID       `json:"id" db:"id"`
	Action     AuditAction     `json:"action" db:"action"`
	EntityType AuditEntityType `json:"entity_type" db:"entity_type"`
	EntityID   *uuid.UUID      `json:"entity_id,omitempty" db:"entity_id"`
	OldValue   json.RawMessage `json:"old_value,omitempty" db:"old_value"`
	NewValue   json.RawMessage `json:"new_value,omitempty" db:"new_value"`
	UserID     *uuid.UUID      `json:"user_id,omitempty" db:"user_id"`
	UserEmail  *string         `json:"user_email,omitempty" db:"user_email"`
	IPAddress  *string         `json:"ip_address,omitempty" db:"ip_address"`
	UserAgent  *string         `json:"user_agent,omitempty" db:"user_agent"`
	CreatedAt  time.Time       `json:"created_at" db:"created_at"`
}

// BlockedContentLog represents a log entry for blocked URLs.
type BlockedContentLog struct {
	ID            uuid.UUID       `json:"id" db:"id"`
	URL           string          `json:"url" db:"url"`
	Domain        string          `json:"domain" db:"domain"`
	BlockReason   BlockReason     `json:"block_reason" db:"block_reason"`
	MatchedRuleID *uuid.UUID      `json:"matched_rule_id,omitempty" db:"matched_rule_id"`
	Details       json.RawMessage `json:"details,omitempty" db:"details"`
	CreatedAt     time.Time       `json:"created_at" db:"created_at"`
}

// =============================================================================
// REQUEST/RESPONSE MODELS
// =============================================================================

// CreateSourcePolicyRequest represents a request to create a new policy.
type CreateSourcePolicyRequest struct {
	Name        string      `json:"name" binding:"required"`
	Description *string     `json:"description"`
	Bundesland  *Bundesland `json:"bundesland"`
}

// UpdateSourcePolicyRequest represents a request to update a policy.
type UpdateSourcePolicyRequest struct {
	Name        *string     `json:"name"`
	Description *string     `json:"description"`
	Bundesland  *Bundesland `json:"bundesland"`
	IsActive    *bool       `json:"is_active"`
}

// CreateAllowedSourceRequest represents a request to create a new allowed source.
type CreateAllowedSourceRequest struct {
	PolicyID         uuid.UUID `json:"policy_id" binding:"required"`
	Domain           string    `json:"domain" binding:"required"`
	Name             string    `json:"name" binding:"required"`
	Description      *string   `json:"description"`
	License          License   `json:"license" binding:"required"`
	LegalBasis       *string   `json:"legal_basis"`
	CitationTemplate *string   `json:"citation_template"`
	TrustBoost       *float64  `json:"trust_boost"`
}

// UpdateAllowedSourceRequest represents a request to update an allowed source.
type UpdateAllowedSourceRequest struct {
	Domain           *string  `json:"domain"`
	Name             *string  `json:"name"`
	Description      *string  `json:"description"`
	License          *License `json:"license"`
	LegalBasis       *string  `json:"legal_basis"`
	CitationTemplate *string  `json:"citation_template"`
	TrustBoost       *float64 `json:"trust_boost"`
	IsActive         *bool    `json:"is_active"`
}

// UpdateOperationPermissionRequest represents a request to update operation permissions.
type UpdateOperationPermissionRequest struct {
	IsAllowed        *bool   `json:"is_allowed"`
	RequiresCitation *bool   `json:"requires_citation"`
	Notes            *string `json:"notes"`
}

// CreatePIIRuleRequest represents a request to create a new PII rule.
type CreatePIIRuleRequest struct {
	Name        string      `json:"name" binding:"required"`
	Description *string     `json:"description"`
	RuleType    PIIRuleType `json:"rule_type" binding:"required"`
	Pattern     string      `json:"pattern" binding:"required"`
	Severity    PIISeverity `json:"severity"`
}

// UpdatePIIRuleRequest represents a request to update a PII rule.
type UpdatePIIRuleRequest struct {
	Name        *string      `json:"name"`
	Description *string      `json:"description"`
	RuleType    *PIIRuleType `json:"rule_type"`
	Pattern     *string      `json:"pattern"`
	Severity    *PIISeverity `json:"severity"`
	IsActive    *bool        `json:"is_active"`
}

// CheckComplianceRequest represents a request to check URL compliance.
type CheckComplianceRequest struct {
	URL        string     `json:"url" binding:"required"`
	Operation  Operation  `json:"operation" binding:"required"`
	Bundesland *Bundesland `json:"bundesland"`
}

// CheckComplianceResponse represents the compliance check result.
type CheckComplianceResponse struct {
	IsAllowed        bool     `json:"is_allowed"`
	Source           *AllowedSource `json:"source,omitempty"`
	BlockReason      *BlockReason   `json:"block_reason,omitempty"`
	RequiresCitation bool     `json:"requires_citation"`
	CitationTemplate *string  `json:"citation_template,omitempty"`
	License          *License `json:"license,omitempty"`
}

// PIITestRequest represents a request to test PII detection.
type PIITestRequest struct {
	Text string `json:"text" binding:"required"`
}

// PIIMatch represents a single PII match in text.
type PIIMatch struct {
	RuleID     uuid.UUID   `json:"rule_id"`
	RuleName   string      `json:"rule_name"`
	RuleType   PIIRuleType `json:"rule_type"`
	Severity   PIISeverity `json:"severity"`
	Match      string      `json:"match"`
	StartIndex int         `json:"start_index"`
	EndIndex   int         `json:"end_index"`
}

// PIITestResponse represents the result of PII detection test.
type PIITestResponse struct {
	HasPII      bool       `json:"has_pii"`
	Matches     []PIIMatch `json:"matches"`
	BlockLevel  PIISeverity `json:"block_level"`
	ShouldBlock bool       `json:"should_block"`
}

// =============================================================================
// LIST/FILTER MODELS
// =============================================================================

// PolicyListFilter represents filters for listing policies.
type PolicyListFilter struct {
	Bundesland *Bundesland `form:"bundesland"`
	IsActive   *bool       `form:"is_active"`
	Limit      int         `form:"limit"`
	Offset     int         `form:"offset"`
}

// SourceListFilter represents filters for listing sources.
type SourceListFilter struct {
	PolicyID   *uuid.UUID `form:"policy_id"`
	Domain     *string    `form:"domain"`
	License    *License   `form:"license"`
	IsActive   *bool      `form:"is_active"`
	Limit      int        `form:"limit"`
	Offset     int        `form:"offset"`
}

// AuditLogFilter represents filters for querying audit logs.
type AuditLogFilter struct {
	EntityType *AuditEntityType `form:"entity_type"`
	EntityID   *uuid.UUID       `form:"entity_id"`
	Action     *AuditAction     `form:"action"`
	UserEmail  *string          `form:"user_email"`
	FromDate   *time.Time       `form:"from"`
	ToDate     *time.Time       `form:"to"`
	Limit      int              `form:"limit"`
	Offset     int              `form:"offset"`
}

// BlockedContentFilter represents filters for querying blocked content logs.
type BlockedContentFilter struct {
	Domain      *string      `form:"domain"`
	BlockReason *BlockReason `form:"block_reason"`
	FromDate    *time.Time   `form:"from"`
	ToDate      *time.Time   `form:"to"`
	Limit       int          `form:"limit"`
	Offset      int          `form:"offset"`
}

// =============================================================================
// STATISTICS MODELS
// =============================================================================

// PolicyStats represents aggregated statistics for the policy system.
type PolicyStats struct {
	ActivePolicies    int            `json:"active_policies"`
	TotalSources      int            `json:"total_sources"`
	ActiveSources     int            `json:"active_sources"`
	BlockedToday      int            `json:"blocked_today"`
	BlockedTotal      int            `json:"blocked_total"`
	PIIRulesActive    int            `json:"pii_rules_active"`
	SourcesByLicense  map[string]int `json:"sources_by_license"`
	BlocksByReason    map[string]int `json:"blocks_by_reason"`
	ComplianceScore   float64        `json:"compliance_score"`
}

// =============================================================================
// YAML CONFIGURATION MODELS
// =============================================================================

// BundeslaenderConfig represents the YAML configuration for initial data loading.
type BundeslaenderConfig struct {
	Federal           PolicyConfig           `yaml:"federal"`
	Bundeslaender     map[string]PolicyConfig `yaml:",inline"`
	DefaultOperations OperationsConfig       `yaml:"default_operations"`
	PIIRules          []PIIRuleConfig        `yaml:"pii_rules"`
}

// PolicyConfig represents a policy configuration in YAML.
type PolicyConfig struct {
	Name    string         `yaml:"name"`
	Sources []SourceConfig `yaml:"sources"`
}

// SourceConfig represents a source configuration in YAML.
type SourceConfig struct {
	Domain           string  `yaml:"domain"`
	Name             string  `yaml:"name"`
	License          string  `yaml:"license"`
	LegalBasis       string  `yaml:"legal_basis,omitempty"`
	CitationTemplate string  `yaml:"citation_template,omitempty"`
	TrustBoost       float64 `yaml:"trust_boost,omitempty"`
}

// OperationsConfig represents default operation permissions in YAML.
type OperationsConfig struct {
	Lookup   OperationConfig `yaml:"lookup"`
	RAG      OperationConfig `yaml:"rag"`
	Training OperationConfig `yaml:"training"`
	Export   OperationConfig `yaml:"export"`
}

// OperationConfig represents a single operation permission in YAML.
type OperationConfig struct {
	Allowed          bool `yaml:"allowed"`
	RequiresCitation bool `yaml:"requires_citation"`
}

// PIIRuleConfig represents a PII rule configuration in YAML.
type PIIRuleConfig struct {
	Name     string `yaml:"name"`
	Type     string `yaml:"type"`
	Pattern  string `yaml:"pattern"`
	Severity string `yaml:"severity"`
}
