"""
User consent tracking models for GDPR compliance
"""

from sqlalchemy import Column, String, Boolean, DateTime, Text, ForeignKey, Index
from sqlalchemy.dialects.postgresql import UUID, JSON
from datetime import datetime, timezone
import uuid

from shared.database.base import Base


class UserConsent(Base):
    """
    Tracks user consent for various data processing activities
    GDPR Article 7 - Conditions for consent
    """
    __tablename__ = "user_consents"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)

    # Consent types
    terms_accepted = Column(Boolean, nullable=False, default=False)
    privacy_accepted = Column(Boolean, nullable=False, default=False)
    marketing_consent = Column(Boolean, nullable=False, default=False)
    analytics_consent = Column(Boolean, nullable=False, default=False)

    # Consent metadata
    consent_version = Column(String(20), nullable=False, default="1.0")
    consent_method = Column(String(50), nullable=False)  # registration, settings_update, cookie_banner
    ip_address = Column(String(45), nullable=True)
    user_agent = Column(Text, nullable=True)

    # Consent text at time of acceptance
    terms_text_hash = Column(String(64), nullable=True)
    privacy_text_hash = Column(String(64), nullable=True)

    # Timestamps
    consented_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc))
    withdrawn_at = Column(DateTime(timezone=True), nullable=True)

    # Additional metadata (renamed from 'metadata' to avoid SQLAlchemy reserved word)
    extra_data = Column(JSON, nullable=True)

    __table_args__ = (
        Index('idx_user_consent_user_id', 'user_id'),
        Index('idx_user_consent_consented_at', 'consented_at'),
    )

    def __repr__(self):
        return f"<UserConsent(user_id={self.user_id}, version={self.consent_version})>"

    def to_dict(self):
        return {
            "id": str(self.id),
            "user_id": str(self.user_id),
            "terms_accepted": self.terms_accepted,
            "privacy_accepted": self.privacy_accepted,
            "marketing_consent": self.marketing_consent,
            "analytics_consent": self.analytics_consent,
            "consent_version": self.consent_version,
            "consent_method": self.consent_method,
            "consented_at": self.consented_at.isoformat() if self.consented_at else None,
            "withdrawn_at": self.withdrawn_at.isoformat() if self.withdrawn_at else None,
        }


class ConsentHistory(Base):
    """
    Historical record of all consent changes
    Provides audit trail for GDPR compliance
    """
    __tablename__ = "consent_history"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    user_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    consent_id = Column(UUID(as_uuid=True), ForeignKey("user_consents.id", ondelete="SET NULL"), nullable=True)

    # Action type
    action = Column(String(50), nullable=False)  # granted, updated, withdrawn, revoked

    # Consent state at time of action
    consent_snapshot = Column(JSON, nullable=False)

    # Context
    ip_address = Column(String(45), nullable=True)
    user_agent = Column(Text, nullable=True)
    consent_method = Column(String(50), nullable=True)

    # Timestamp
    created_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc), index=True)

    __table_args__ = (
        Index('idx_consent_history_user_id', 'user_id'),
        Index('idx_consent_history_created_at', 'created_at'),
        Index('idx_consent_history_action', 'action'),
    )

    def __repr__(self):
        return f"<ConsentHistory(user_id={self.user_id}, action={self.action})>"

    def to_dict(self):
        return {
            "id": str(self.id),
            "user_id": str(self.user_id),
            "action": self.action,
            "consent_snapshot": self.consent_snapshot,
            "created_at": self.created_at.isoformat() if self.created_at else None,
        }
