"""
Authentication audit log model for tracking auth events.

Provides traceability for Loi 25 compliance: login/logout history, failed attempts.
"""

from datetime import datetime
from src.database import db


class AuthLog(db.Model):
    """Audit trail for authentication events."""

    __tablename__ = 'auth_log'

    id = db.Column(db.Integer, primary_key=True)

    # Who (nullable for failed logins where user doesn't exist)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
    user = db.relationship('User', backref=db.backref('auth_logs', lazy='dynamic'))

    # What
    action = db.Column(db.String(30), nullable=False)  # 'login', 'logout', 'failed_login', 'register', 'password_change', 'password_reset', 'sso_login'

    # When
    timestamp = db.Column(db.DateTime, default=datetime.utcnow, nullable=False, index=True)

    # Where from
    ip_address = db.Column(db.String(45), nullable=True)
    user_agent = db.Column(db.String(500), nullable=True)

    # Extra context (JSON) — e.g. email attempted, SSO provider, reason for failure
    details = db.Column(db.JSON, nullable=True)

    def to_dict(self):
        """Convert to dictionary for API responses."""
        return {
            'id': self.id,
            'user_id': self.user_id,
            'username': self.user.username if self.user else None,
            'action': self.action,
            'timestamp': self.timestamp.isoformat() if self.timestamp else None,
            'ip_address': self.ip_address,
            'user_agent': self.user_agent,
            'details': self.details,
        }

    @staticmethod
    def log_auth(action, user_id=None, ip_address=None, user_agent=None, details=None):
        """Log an authentication event."""
        log = AuthLog(
            user_id=user_id,
            action=action,
            ip_address=ip_address,
            user_agent=user_agent,
            details=details,
        )
        db.session.add(log)
        return log

    @staticmethod
    def log_login(user_id, ip_address=None, user_agent=None, details=None):
        """Log a successful login."""
        return AuthLog.log_auth('login', user_id=user_id, ip_address=ip_address, user_agent=user_agent, details=details)

    @staticmethod
    def log_logout(user_id, ip_address=None, user_agent=None):
        """Log a logout."""
        return AuthLog.log_auth('logout', user_id=user_id, ip_address=ip_address, user_agent=user_agent)

    @staticmethod
    def log_failed_login(ip_address=None, user_agent=None, details=None):
        """Log a failed login attempt."""
        return AuthLog.log_auth('failed_login', ip_address=ip_address, user_agent=user_agent, details=details)

    @staticmethod
    def log_register(user_id, ip_address=None, user_agent=None):
        """Log a new user registration."""
        return AuthLog.log_auth('register', user_id=user_id, ip_address=ip_address, user_agent=user_agent)

    @staticmethod
    def log_password_change(user_id, ip_address=None, user_agent=None, details=None):
        """Log a password change."""
        return AuthLog.log_auth('password_change', user_id=user_id, ip_address=ip_address, user_agent=user_agent, details=details)

    @staticmethod
    def log_password_reset(user_id, ip_address=None, user_agent=None):
        """Log a password reset."""
        return AuthLog.log_auth('password_reset', user_id=user_id, ip_address=ip_address, user_agent=user_agent)

    @staticmethod
    def log_sso_login(user_id, ip_address=None, user_agent=None, details=None):
        """Log an SSO login."""
        return AuthLog.log_auth('sso_login', user_id=user_id, ip_address=ip_address, user_agent=user_agent, details=details)
