"""
用户注册 Use Case
"""

import secrets
from datetime import datetime, timedelta, timezone
from typing import Optional
from uuid import uuid4

from packages.adapters.smtp import get_email_service
from packages.application.auth.password_hasher import password_hasher, password_validator
from packages.domain.entities import User


class RegisterUserRequest:
    """注册请求"""

    def __init__(
        self,
        email: str,
        password: str,
        username: str,
        display_name: str,
    ):
        self.email = email.strip().lower()
        self.password = password
        self.username = username.strip()
        self.display_name = display_name.strip()


class RegisterUserResponse:
    """注册响应"""

    def __init__(
        self,
        user_id: str,
        email: str,
        username: str,
        display_name: str,
        email_verification_sent: bool,
    ):
        self.user_id = user_id
        self.email = email
        self.username = username
        self.display_name = display_name
        self.email_verification_sent = email_verification_sent


class RegisterUserUseCase:
    """用户注册用例"""

    def __init__(
        self,
        user_repository,
        base_url: str,
        email_service=None,
    ):
        """
        初始化注册用例

        Args:
            user_repository: 用户仓储
            base_url: 应用基础 URL（用于生成验证链接），必须由调用方传入
        """
        self.user_repository = user_repository
        self.base_url = base_url
        self.email_service = email_service or get_email_service()

    def execute(self, request: RegisterUserRequest) -> tuple[Optional[RegisterUserResponse], Optional[str]]:
        """
        执行注册

        Args:
            request: 注册请求

        Returns:
            (注册响应, 错误信息)
        """
        try:
            # 1. 验证输入
            if not request.email:
                return None, "Email is required"

            if not request.username:
                return None, "Username is required"

            if not request.display_name:
                return None, "Display name is required"

            # 2. 验证密码强度
            valid, error = password_validator.validate(request.password)
            if not valid:
                return None, error

            # 3. 检查邮箱是否已存在
            existing_user = self.user_repository.find_by_email(request.email)
            if existing_user:
                return None, "Email already registered"

            # 4. 检查用户名是否已存在
            existing_username = self.user_repository.find_by_username(request.username)
            if existing_username:
                return None, "Username already taken"

            # 5. 哈希密码
            hashed_password = password_hasher.hash_password(request.password)

            # 6. 生成邮箱验证令牌
            verification_token = secrets.token_urlsafe(32)

            # 7. 创建用户
            user = User(
                id=uuid4().hex,
                email=request.email,
                username=request.username,
                display_name=request.display_name,
                password_hash=hashed_password,
                email_verified=False,
                email_verification_token=verification_token,
                created_at=datetime.now(timezone.utc),
            )

            # 8. 保存用户
            self.user_repository.save(user)

            # 9. 发送验证邮件
            verification_url = f"{self.base_url}/verify-email?token={verification_token}"
            email_sent = False

            try:
                success, error = self.email_service.send_verification_email(
                    to_email=user.email,
                    username=user.username,
                    verification_url=verification_url,
                )
                email_sent = success

                if not success:
                    print(f"Failed to send verification email: {error}")
            except Exception as e:
                print(f"Email service error: {e}")

            # 10. 返回响应（即使邮件发送失败，用户也已创建）
            return (
                RegisterUserResponse(
                    user_id=user.id,
                    email=user.email,
                    username=user.username,
                    display_name=user.display_name,
                    email_verification_sent=email_sent,
                ),
                None,
            )

        except Exception as e:
            return None, f"Registration failed: {str(e)}"


class VerifyEmailRequest:
    """邮箱验证请求"""

    def __init__(self, token: str):
        self.token = token


class VerifyEmailUseCase:
    """邮箱验证用例"""

    def __init__(self, user_repository):
        self.user_repository = user_repository

    def execute(self, request: VerifyEmailRequest) -> tuple[bool, Optional[str]]:
        """
        执行邮箱验证

        Args:
            request: 验证请求

        Returns:
            (是否成功, 错误信息)
        """
        try:
            if not request.token:
                return False, "Verification token is required"

            # 查找用户
            user = self.user_repository.find_by_verification_token(request.token)
            if not user:
                return False, "Invalid or expired verification token"

            # 检查是否已验证
            if user.email_verified:
                return True, None  # 已验证，返回成功

            # 更新用户状态
            user.email_verified = True
            user.email_verification_token = None  # 清空令牌

            self.user_repository.save(user)

            return True, None

        except Exception as e:
            return False, f"Email verification failed: {str(e)}"
