from typing import Final

from dirty_equals import IsDict, IsPartialDict, IsStr
from dishka import FromDishka

from tests.web_api.helpers import (
    is_conflict_response,
    is_not_found_response,
    is_success_response,
    is_unauthorized_response,
)
from tests.web_api.ioc import DatabaseClearer, inject
from tests.web_api.test_api_gateway import TestApiGateway

DEFAULT_PASSWORD: Final = "Sup3rPuperS3cret"  # noqa: S105


@inject
async def test_email_sign_up_creates_user(
    unique_email: str,
    test_api_gateway: FromDishka[TestApiGateway],
    database_clearer: FromDishka[DatabaseClearer],
) -> None:
    await database_clearer.clear()

    response = await test_api_gateway.sign_up_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )
    assert is_success_response(response)
    assert response.json() == IsPartialDict(access_token=IsStr())


@inject
async def test_email_sign_up_existing_user_conflict(
    unique_email: str,
    test_api_gateway: FromDishka[TestApiGateway],
    database_clearer: FromDishka[DatabaseClearer],
) -> None:
    await database_clearer.clear()

    await test_api_gateway.sign_up_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )

    response = await test_api_gateway.sign_up_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )
    assert is_conflict_response(response)


@inject
async def test_email_sign_in_returns_token(
    unique_email: str,
    test_api_gateway: FromDishka[TestApiGateway],
    database_clearer: FromDishka[DatabaseClearer],
) -> None:
    await database_clearer.clear()

    await test_api_gateway.sign_up_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )

    response = await test_api_gateway.sign_in_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )
    assert is_success_response(response)
    assert response.json() == IsDict(
        access_token=IsStr,
    )


@inject
async def test_email_sign_in_invalid_password(
    unique_email: str,
    test_api_gateway: FromDishka[TestApiGateway],
    database_clearer: FromDishka[DatabaseClearer],
) -> None:
    await database_clearer.clear()

    await test_api_gateway.sign_up_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )

    response = await test_api_gateway.sign_in_email(
        email=unique_email,
        password="wrong-password",
    )
    assert is_unauthorized_response(response)


@inject
async def test_email_sign_in_user_not_found(
    unique_email: str,
    test_api_gateway: FromDishka[TestApiGateway],
    database_clearer: FromDishka[DatabaseClearer],
) -> None:
    await database_clearer.clear()

    response = await test_api_gateway.sign_in_email(
        email=unique_email,
        password=DEFAULT_PASSWORD,
    )

    assert is_not_found_response(response)
