"""
Email verification workflow - Feature 8

Secure email verification flow using time-limited tokens.
"""

from datetime import datetime, timedelta
from typing import Optional
from sqlalchemy.orm import Session

from .config import AuthConfig
from .models import User

# Import Rust crypto functions
try:
    from .irene_auth import generate_token, hash_token, verify_token_hash
except ImportError:
    import irene_auth as _rust
    generate_token = _rust.generate_token
    hash_token = _rust.hash_token
    verify_token_hash = _rust.verify_token_hash


class EmailVerificationManager:
    """
    Email verification manager - Feature 8
    
    Implements secure email verification workflow:
    1. On signup, generate verification token (Rust CSPRNG)
    2. Hash and store token (Rust SHA-256)
    3. Send email with plaintext token
    4. User clicks link with token
    5. Verify token (Rust constant-time)
    6. Mark user as verified
    7. Invalidate token
    """
    
    def __init__(self, config: AuthConfig):
        self.config = config
    
    def create_verification_token(self, user: User, db: Session) -> str:
        """
        Create email verification token for user
        
        Args:
            user: User object (not yet verified)
            db: Database session
        
        Returns:
            Verification token (send to user via email)
        
        Security:
            - Token generated with CSPRNG (Rust)
            - Only hash stored in database
            - Token expires after configured time (default: 24 hours)
        
        Example:
            >>> token = verification_manager.create_verification_token(user, db)
            >>> send_email(user.email, f"Verify: https://example.com/verify?token={token}")
        """
        # Generate secure token (Rust)
        token = generate_token(32)
        
        # Hash for storage (Rust)
        token_hash = hash_token(token)
        
        # Set expiration
        expires = datetime.utcnow() + timedelta(hours=self.config.verification_token_expire_hours)
        
        # Store hash and expiration
        user.verification_token_hash = token_hash
        user.verification_token_expires = expires
        user.is_verified = False
        db.commit()
        
        return token
    
    def verify_email(self, token: str, db: Session) -> bool:
        """
        Verify user's email with token
        
        Args:
            token: Plaintext verification token
            db: Database session
        
        Returns:
            True if email was verified, False otherwise
        
        Security:
            - Uses constant-time comparison (Rust)
            - Checks expiration
            - Invalidates token after successful verification
        
        Example:
            >>> if verification_manager.verify_email(token, db):
            ...     print("Email verified successfully!")
        """
        # Get users with active verification tokens
        users = db.query(User).filter(
            User.verification_token_hash.isnot(None),
            User.verification_token_expires.isnot(None),
            User.is_verified == False
        ).all()
        
        # Check each user's token with constant-time comparison (Rust)
        for user in users:
            if verify_token_hash(token, user.verification_token_hash):
                # Check expiration
                if user.verification_token_expires > datetime.utcnow():
                    # Mark as verified
                    user.is_verified = True
                    user.verification_token_hash = None
                    user.verification_token_expires = None
                    db.commit()
                    return True
                else:
                    # Token expired - clean up
                    user.verification_token_hash = None
                    user.verification_token_expires = None
                    db.commit()
                    return False
        
        return False
    
    def resend_verification(self, email: str, db: Session) -> Optional[str]:
        """
        Resend verification email to user
        
        Args:
            email: User's email address
            db: Database session
        
        Returns:
            New verification token or None if user doesn't exist or is already verified
        
        Example:
            >>> token = verification_manager.resend_verification("user@example.com", db)
            >>> if token:
            ...     send_email(email, f"Verify: {token}")
        """
        user = db.query(User).filter_by(email=email).first()
        
        if not user:
            return None
        
        if user.is_verified:
            return None  # Already verified
        
        # Generate new token
        return self.create_verification_token(user, db)
    
    def is_token_expired(self, email: str, db: Session) -> bool:
        """
        Check if user's verification token has expired
        
        Args:
            email: User's email
            db: Database session
        
        Returns:
            True if token exists but has expired, False otherwise
        """
        user = db.query(User).filter_by(email=email).first()
        
        if not user or not user.verification_token_expires:
            return False
        
        return user.verification_token_expires < datetime.utcnow()
