from datetime import UTC

import pytest
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError

from bluefox_auth.models import BluefoxUser, RefreshToken


async def test_bluefox_user__creates_with_required_fields(db):
    user = BluefoxUser(
        email="test@example.com",
        password_hash="hashed_password",
    )
    db.add(user)
    await db.flush()

    assert user.id is not None
    assert user.email == "test@example.com"
    assert user.password_hash == "hashed_password"


async def test_bluefox_user__defaults(db):
    user = BluefoxUser(
        email="defaults@example.com",
        password_hash="hashed_password",
    )
    db.add(user)
    await db.flush()

    assert user.is_active is True
    assert user.is_superuser is False
    assert user.email_verified is False


async def test_bluefox_user__email_unique_constraint(db):
    user1 = BluefoxUser(email="dupe@example.com", password_hash="hash1")
    user2 = BluefoxUser(email="dupe@example.com", password_hash="hash2")
    db.add(user1)
    await db.flush()
    db.add(user2)
    with pytest.raises(IntegrityError):
        await db.flush()


async def test_bluefox_user__timestamps_set_on_create(db):
    user = BluefoxUser(email="ts@example.com", password_hash="hash")
    db.add(user)
    await db.flush()
    await db.refresh(user)

    assert user.created_at is not None
    assert user.updated_at is not None


async def test_refresh_token__creates_with_required_fields(db):
    user = BluefoxUser(email="rt@example.com", password_hash="hash")
    db.add(user)
    await db.flush()

    from datetime import datetime

    token = RefreshToken(
        jti="test-jti-001",
        user_id=user.id,
        family_id="family-001",
        expires_at=datetime(2099, 1, 1, tzinfo=UTC),
    )
    db.add(token)
    await db.flush()

    assert token.id is not None
    assert token.jti == "test-jti-001"
    assert token.user_id == user.id
    assert token.family_id == "family-001"
    assert token.is_revoked is False


async def test_refresh_token__jti_unique_constraint(db):
    user = BluefoxUser(email="jti@example.com", password_hash="hash")
    db.add(user)
    await db.flush()

    from datetime import datetime

    expires = datetime(2099, 1, 1, tzinfo=UTC)
    t1 = RefreshToken(jti="dupe-jti", user_id=user.id, family_id="f1", expires_at=expires)
    t2 = RefreshToken(jti="dupe-jti", user_id=user.id, family_id="f2", expires_at=expires)
    db.add(t1)
    await db.flush()
    db.add(t2)
    with pytest.raises(IntegrityError):
        await db.flush()


async def test_refresh_token__cascade_deletes_on_user_delete(db):
    user = BluefoxUser(email="cascade@example.com", password_hash="hash")
    db.add(user)
    await db.flush()

    from datetime import datetime

    token = RefreshToken(
        jti="cascade-jti",
        user_id=user.id,
        family_id="f1",
        expires_at=datetime(2099, 1, 1, tzinfo=UTC),
    )
    db.add(token)
    await db.flush()

    await db.delete(user)
    await db.flush()

    result = await db.execute(select(RefreshToken).where(RefreshToken.jti == "cascade-jti"))
    assert result.scalar_one_or_none() is None
