"""
Signup function - standalone, no database required.
"""

import secrets
from datetime import datetime, timedelta, timezone
from typing import Dict, Any

from apexsaas.core.security.password import get_password_hash
from apexsaas.core.security.jwt import create_access_token, create_refresh_token
from apexsaas.email import send_welcome_email
from apexsaas.exceptions import ApexValidationError, ApexEmailError


async def signup(
    email: str,
    password: str,
    name: str,
    sendgrid_api_key: str,
    from_email: str,
    jwt_secret: str = None,
    expires_in: int = 3600,
    user_metadata: Dict[str, Any] = None,
    app_url: str = None,
    **kwargs  # Accept any additional custom fields as direct parameters
) -> Dict[str, Any]:
    """
    Signup a new user (async).
    
    Args:
        email: User email address
        password: User password (will be hashed)
        name: User name
        sendgrid_api_key: SendGrid API key for sending welcome email
        from_email: Sender email address
        jwt_secret: Secret key for JWT (optional, generates if not provided)
        expires_in: Token expiration time in seconds (default: 3600)
        user_metadata: Optional dictionary with additional user fields (e.g., phone, company, address, etc.)
        app_url: Optional application URL for welcome email (default: None)
        **kwargs: Additional custom fields as direct parameters (e.g., phone="+123", company="Acme")
                 These will be merged with user_metadata (kwargs take precedence)
    
    Returns:
        dict with user data, tokens, and email status:
        {
            'user': {
                'email': str,
                'name': str,
                'password_hash': str,
                'created_at': str,
                ... (any additional fields from user_metadata)
            },
            'access_token': str,
            'refresh_token': str,
            'email_sent': bool
        }
    
    Raises:
        ApexValidationError: If input validation fails
        ApexEmailError: If email sending fails
    """
    if not email or not isinstance(email, str):
        raise ApexValidationError("Email is required")
    if not password or len(password) < 8:
        raise ApexValidationError("Password must be at least 8 characters")
    if not name or not isinstance(name, str):
        raise ApexValidationError("Name is required")
    if not sendgrid_api_key:
        raise ApexValidationError("sendgrid_api_key is required")
    if not from_email:
        raise ApexValidationError("from_email is required")
    
    # Hash password
    password_hash = get_password_hash(password)
    
    # Generate JWT tokens
    if not jwt_secret:
        jwt_secret = secrets.token_urlsafe(32)
    
    # Merge user_metadata and kwargs (kwargs take precedence)
    all_metadata = {}
    if user_metadata:
        all_metadata.update(user_metadata)
    if kwargs:
        all_metadata.update(kwargs)
    
    # Build token data with core fields
    token_data = {
        "sub": email,
        "email": email,
        "name": name
    }
    
    # Add safe metadata fields to token (exclude sensitive fields)
    if all_metadata:
        # Fields to exclude from JWT token (sensitive or too large)
        excluded_fields = {'password', 'password_hash', 'credit_card', 'ssn', 'api_key', 'secret'}
        for key, value in all_metadata.items():
            if key.lower() not in excluded_fields and isinstance(value, (str, int, float, bool)):
                token_data[key] = value
    
    access_token = create_access_token(data=token_data, expires_delta=timedelta(seconds=expires_in), secret_key=jwt_secret)
    refresh_token = create_refresh_token(data=token_data, secret_key=jwt_secret)
    
    # Build user data with core fields
    user_data = {
        'email': email,
        'name': name,
        'password_hash': password_hash,
        'created_at': datetime.now(timezone.utc).isoformat()
    }
    
    # Add any additional metadata fields (from user_metadata or kwargs)
    if all_metadata:
        user_data.update(all_metadata)
    
    # Send welcome email
    email_sent = False
    email_message = None
    try:
        email_result = await send_welcome_email(
            to_email=email,
            to_name=name,
            sendgrid_api_key=sendgrid_api_key,
            from_email=from_email,
            app_url=app_url
        )
        email_sent = email_result.get('success', False)
        email_message = email_result.get('message', 'Email sending status unknown')
    except Exception as e:
        # Don't fail signup if email fails - email_sent will be False
        email_message = f"Failed to send welcome email: {str(e)}"
    
    return {
        'user': user_data,
        'access_token': access_token,
        'refresh_token': refresh_token,
        'email_sent': email_sent,
        'message': email_message if email_message else ('Welcome email sent successfully' if email_sent else 'Failed to send welcome email')
    }


def signup_sync(
    email: str,
    password: str,
    name: str,
    sendgrid_api_key: str,
    from_email: str,
    jwt_secret: str = None,
    expires_in: int = 3600,
    user_metadata: Dict[str, Any] = None,
    app_url: str = None,
    **kwargs
) -> Dict[str, Any]:
    """Sync wrapper for signup."""
    from apexsaas.core.utils.async_runner import run_async
    try:
        return run_async(signup(
            email=email,
            password=password,
            name=name,
            sendgrid_api_key=sendgrid_api_key,
            from_email=from_email,
            jwt_secret=jwt_secret,
            expires_in=expires_in,
            user_metadata=user_metadata,
            app_url=app_url,
            **kwargs
        ))
    except Exception as e:
        raise ApexValidationError(f"Signup failed: {str(e)}")
