"""GDPR privacy and data protection specification.

Defines data classification, retention policies, and GDPR data subject rights
configuration for Prism-generated applications.
"""

from __future__ import annotations

from enum import StrEnum

from pydantic import BaseModel, Field, field_validator


class DataClassification(StrEnum):
    """GDPR data classification levels.

    Used to tag individual fields with their sensitivity level,
    driving automatic protections like audit logging, log redaction,
    and encryption.
    """

    PUBLIC = "public"
    INTERNAL = "internal"
    CONFIDENTIAL = "confidential"
    HIGHLY_CONFIDENTIAL = "highly_confidential"


class LegalBasis(StrEnum):
    """GDPR legal basis for processing personal data (Article 6)."""

    CONSENT = "consent"
    CONTRACT = "contract"
    LEGAL_OBLIGATION = "legal_obligation"
    VITAL_INTERESTS = "vital_interests"
    PUBLIC_TASK = "public_task"
    LEGITIMATE_INTERESTS = "legitimate_interests"


class FieldPrivacyConfig(BaseModel):
    """Per-field privacy settings.

    Attached to individual FieldSpec entries to classify data
    and control how it is stored, logged, and accessed.

    Example:
        >>> privacy = FieldPrivacyConfig(
        ...     classification=DataClassification.CONFIDENTIAL,
        ...     is_pii=True,
        ...     redact_in_logs=True,
        ... )
    """

    classification: DataClassification = Field(
        default=DataClassification.INTERNAL,
        description="Data classification level for this field",
    )
    is_pii: bool = Field(
        default=False,
        description="Whether this field contains personally identifiable information",
    )
    redact_in_logs: bool = Field(
        default=False,
        description="Redact this field's value in application logs",
    )
    audit_access: bool = Field(
        default=False,
        description="Log every read access to this field in the audit trail",
    )
    encrypt_at_rest: bool = Field(
        default=False,
        description="Encrypt this field at the database level",
    )

    model_config = {"extra": "forbid"}


class RetentionPolicy(BaseModel):
    """Data retention and automatic deletion policy.

    Controls how long records are kept and when they are purged.

    Example:
        >>> policy = RetentionPolicy(
        ...     retention_days=365,
        ...     auto_delete=True,
        ...     archive_before_delete=True,
        ... )
    """

    retention_days: int = Field(
        ...,
        gt=0,
        description="Number of days to retain records before they are eligible for deletion",
    )
    auto_delete: bool = Field(
        default=False,
        description="Automatically hard-delete records after the retention period",
    )
    archive_before_delete: bool = Field(
        default=True,
        description="Export records to an archive before deletion",
    )
    soft_delete_first: bool = Field(
        default=True,
        description="Soft-delete records before hard-deleting after retention",
    )

    model_config = {"extra": "forbid"}


class DataSubjectRightsConfig(BaseModel):
    """GDPR data subject rights configuration per model.

    Controls which GDPR rights are generated for a model that
    stores personal data.

    Example:
        >>> rights = DataSubjectRightsConfig(
        ...     right_to_access=True,
        ...     right_to_erasure=True,
        ...     right_to_portability=True,
        ...     export_formats=["json", "csv"],
        ... )
    """

    right_to_access: bool = Field(
        default=True,
        description="Generate data export endpoint (GDPR Article 15)",
    )
    right_to_erasure: bool = Field(
        default=True,
        description="Generate data deletion/anonymization endpoint (GDPR Article 17)",
    )
    right_to_rectification: bool = Field(
        default=True,
        description="Audit all update operations for compliance (GDPR Article 16)",
    )
    right_to_portability: bool = Field(
        default=True,
        description="Generate multi-format data export (GDPR Article 20)",
    )
    right_to_restrict_processing: bool = Field(
        default=False,
        description="Generate processing restriction toggle (GDPR Article 18)",
    )
    export_formats: list[str] = Field(
        default_factory=lambda: ["json", "csv"],
        description="Supported export formats for data portability",
    )

    @field_validator("export_formats")
    @classmethod
    def validate_export_formats(cls, v: list[str]) -> list[str]:
        allowed = {"json", "csv", "xml"}
        for fmt in v:
            if fmt not in allowed:
                msg = f"Unsupported export format '{fmt}'. Allowed: {sorted(allowed)}"
                raise ValueError(msg)
        return v

    model_config = {"extra": "forbid"}


class GDPRModelConfig(BaseModel):
    """Per-model GDPR configuration.

    Combines data subject rights with retention policies and
    legal basis tracking.

    Example:
        >>> gdpr = GDPRModelConfig(
        ...     is_personal_data=True,
        ...     legal_basis=LegalBasis.CONTRACT,
        ...     data_subject_rights=DataSubjectRightsConfig(),
        ...     retention=RetentionPolicy(retention_days=730),
        ... )
    """

    is_personal_data: bool = Field(
        default=False,
        description="Whether this model stores personal data subject to GDPR",
    )
    legal_basis: LegalBasis = Field(
        default=LegalBasis.LEGITIMATE_INTERESTS,
        description="Legal basis for processing data in this model (GDPR Article 6)",
    )
    purpose: str = Field(
        default="",
        description="Purpose of processing for this model (shown in documentation)",
    )
    data_subject_rights: DataSubjectRightsConfig = Field(
        default_factory=DataSubjectRightsConfig,
        description="GDPR data subject rights configuration",
    )
    retention: RetentionPolicy | None = Field(
        default=None,
        description="Data retention policy (None = keep indefinitely)",
    )
    anonymize_on_delete: bool = Field(
        default=False,
        description="Anonymize PII fields instead of deleting entire records",
    )

    model_config = {"extra": "forbid"}


class PrivacyConfig(BaseModel):
    """Project-level privacy and GDPR configuration.

    Enables GDPR compliance features across the generated application
    including audit logging, data export, retention policies,
    and compliance documentation.

    Example:
        >>> privacy = PrivacyConfig(
        ...     enabled=True,
        ...     organization_name="Acme Corp",
        ...     dpo_email="dpo@acme.com",
        ...     privacy_policy_url="https://acme.com/privacy",
        ... )
    """

    enabled: bool = Field(
        default=False,
        description="Enable GDPR privacy features generation",
    )
    organization_name: str = Field(
        default="",
        description="Organization name for compliance documents",
    )
    dpo_email: str = Field(
        default="",
        description="Data Protection Officer email address",
    )
    privacy_policy_url: str = Field(
        default="",
        description="URL to the organization's privacy policy",
    )
    data_processing_region: str = Field(
        default="EU",
        description="Primary data processing region (e.g. EU, US, UK)",
    )
    generate_audit_log: bool = Field(
        default=True,
        description="Generate audit log model and middleware for tracking data access",
    )
    generate_compliance_docs: bool = Field(
        default=True,
        description="Generate GDPR and NIS2 compliance documentation",
    )
    generate_retention_jobs: bool = Field(
        default=True,
        description="Generate background jobs for data retention enforcement",
    )
    nis2_enabled: bool = Field(
        default=False,
        description="Enable NIS2 compliance documentation generation",
    )
    nis2_sector: str = Field(
        default="",
        description="NIS2 sector classification (e.g. 'digital_infrastructure', 'healthcare')",
    )
    nis2_entity_type: str = Field(
        default="essential",
        description="NIS2 entity type: 'essential' or 'important'",
    )
    subprocessors: list[str] = Field(
        default_factory=list,
        description="List of third-party data subprocessors",
    )

    @field_validator("nis2_entity_type")
    @classmethod
    def validate_nis2_entity_type(cls, v: str) -> str:
        if v and v not in ("essential", "important"):
            msg = f"NIS2 entity type must be 'essential' or 'important', got '{v}'"
            raise ValueError(msg)
        return v

    model_config = {"extra": "forbid"}


__all__ = [
    "DataClassification",
    "DataSubjectRightsConfig",
    "FieldPrivacyConfig",
    "GDPRModelConfig",
    "LegalBasis",
    "PrivacyConfig",
    "RetentionPolicy",
]
