"""VerificationCode 领域实体单测."""

from datetime import datetime, timedelta, timezone

import pytest

from packages.domain.verification_code import VerificationCode


class TestVerificationCodeCreate:
    def test_create_default_ttl(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
        assert code.id
        assert code.recipient == "test@example.com"
        assert code.code_type == "email_bind"
        assert len(code.code) == 6
        assert code.code.isdigit()
        assert code.used_at is None
        assert code.attempts == 0
        # 默认5分钟过期
        assert code.expires_at > code.created_at
        assert (code.expires_at - code.created_at).total_seconds() == pytest.approx(300, abs=1)

    def test_create_custom_ttl(self):
        code = VerificationCode.create(recipient="13800138000", code_type="phone_login", ttl_seconds=60)
        assert (code.expires_at - code.created_at).total_seconds() == pytest.approx(60, abs=1)

    def test_create_custom_code(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="reset_password", custom_code="123456")
        assert code.code == "123456"

    def test_create_recipient_stripped(self):
        code = VerificationCode.create(recipient="  test@example.com  ", code_type="email_bind")
        assert code.recipient == "test@example.com"


class TestVerificationCodeStatus:
    def test_is_valid_initial(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
        assert code.is_valid is True
        assert code.is_expired is False
        assert code.is_used is False

    def test_mark_used(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
        code.mark_used()
        assert code.is_used is True
        assert code.used_at is not None
        assert code.is_valid is False

    def test_is_expired_future(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind", ttl_seconds=3600)
        assert code.is_expired is False

    def test_increment_attempts(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind")
        assert code.attempts == 0
        code.increment_attempts()
        assert code.attempts == 1
        code.increment_attempts()
        assert code.attempts == 2

    def test_is_valid_after_expired(self):
        code = VerificationCode.create(recipient="test@example.com", code_type="email_bind", ttl_seconds=0)
        # 0秒TTL，立即可能过期（有极小概率因时间差没过）
        import time

        time.sleep(0.01)
        assert code.is_expired is True
        assert code.is_valid is False
