import pytest
from unittest.mock import MagicMock, patch
from app.services.auth_service import AuthService
from app.schemas import LoginSchema
from app.exception import AuthException
from werkzeug.security import generate_password_hash


@pytest.fixture
def mock_user_repository():
    return MagicMock()


@pytest.fixture
def auth_service(mock_user_repository):
    return AuthService(userRepository=mock_user_repository)


@pytest.fixture
def dummy_user():
    return MagicMock(
        id="user123",
        email="user@example.com",
        password=generate_password_hash("secret"),
    )


# --- verify_google_id_token tests ---


@patch("app.services.auth_service.id_token.verify_oauth2_token")
def test_verify_google_existing_user(
    mock_verify, auth_service, mock_user_repository, dummy_user
):
    # Simulate valid token
    mock_verify.return_value = {"sub": "google-id-123", "email": "user@example.com"}
    mock_user_repository.get_by_google_id.return_value = dummy_user

    user = auth_service.verify_google_id_token("valid_token")
    assert user == dummy_user
    mock_user_repository.get_by_google_id.assert_called_once()


@patch("app.services.auth_service.id_token.verify_oauth2_token")
def test_verify_google_new_user(
    mock_verify, auth_service, mock_user_repository, dummy_user
):
    mock_verify.return_value = {
        "sub": "new-google-id",
        "email": "newuser@example.com",
        "name": "New User",
    }
    mock_user_repository.get_by_google_id.return_value = None
    mock_user_repository.insert_user.return_value = "new-user-id"
    mock_user_repository.get_user_by_id.return_value = dummy_user

    with patch(
        "app.services.auth_service.UserMapper.from_google_payload"
    ) as mock_mapper:
        mock_mapper.return_value = dummy_user
        user = auth_service.verify_google_id_token("new_token")

    assert user == dummy_user
    mock_user_repository.insert_user.assert_called_once()
    mock_user_repository.get_user_by_id.assert_called_once_with(user_id="new-user-id")


@patch("app.services.auth_service.id_token.verify_oauth2_token")
def test_verify_google_email_mismatch(
    mock_verify, auth_service, mock_user_repository, dummy_user
):
    mock_verify.return_value = {"sub": "google-id-123", "email": "wrong@example.com"}
    dummy_user.email = "correct@example.com"
    mock_user_repository.get_by_google_id.return_value = dummy_user

    with pytest.raises(AuthException, match="Email not match"):
        auth_service.verify_google_id_token("token")


# @patch("app.services.auth_service.id_token.verify_oauth2_token")
# def test_verify_google_invalid_token(mock_verify, auth_service):
#     mock_verify.side_effect = ValueError("Invalid token")

#     with pytest.raises(AuthException):
#         auth_service.verify_google_id_token("invalid_token")


# --- login tests ---


def test_login_success(auth_service, mock_user_repository, dummy_user):
    mock_user_repository.get_user_by_email.return_value = dummy_user
    schema = LoginSchema(email="user@example.com", password="secret")

    user = auth_service.login(schema)
    assert user.email == "user@example.com"
    assert user.password is None


def test_login_wrong_password(auth_service, mock_user_repository, dummy_user):
    mock_user_repository.get_user_by_email.return_value = dummy_user
    schema = LoginSchema(email="user@example.com", password="wrong")

    user = auth_service.login(schema)
    assert user is None


def test_login_user_not_found(auth_service, mock_user_repository):
    mock_user_repository.get_user_by_email.return_value = None
    schema = LoginSchema(email="unknown@example.com", password="any")

    user = auth_service.login(schema)
    assert user is None
