from typing import Final

from dirty_equals import IsDict, IsOneOf, IsPartialDict, IsUUID
from dishka import FromDishka
from uuid_utils.compat import uuid7

from tests.web_api.helpers import (
    is_forbidden_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 = "Sup3rSecret"  # noqa: S105


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.create_resume(
        access_token=access_token,
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )
    assert is_success_response(response)
    assert response.json() == IsDict(
        resume_id=IsUUID(),
    )


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

    response = await test_api_gateway.create_resume(
        access_token="...",
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )
    assert is_unauthorized_response(response)


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.create_resume(
        access_token=access_token,
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )

    response = await test_api_gateway.get_resume(
        access_token=access_token,
        resume_id=response.json()["resume_id"],
    )
    assert is_success_response(response)
    json_response = response.json()
    assert json_response == IsPartialDict(
        position="Position",
        location="Moscow",
        about_me="About me",
        key_skills=["i love lisp", "i love rust"],
        experience_type="noExperience",
        experience=[],
        education=[],
        projects=[],
    )
    assert json_response["prediction"] == IsOneOf(
        None,
        IsPartialDict(
            from_salary="0",
            to_salary="0",
            recommended_skills=[],
        ),
    )


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.create_resume(
        access_token=access_token,
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )

    response = await test_api_gateway.get_resume(
        access_token="...",
        resume_id=response.json()["resume_id"],
    )
    assert is_unauthorized_response(response)


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.get_resume(
        access_token=access_token,
        resume_id=str(uuid7()),
    )
    assert is_not_found_response(response)


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.create_resume(
        access_token=access_token,
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )
    resume_id = response.json()["resume_id"]
    response = await test_api_gateway.edit_resume(
        access_token=access_token,
        resume_id=resume_id,
        about_me="Updated about me",
        experience_type="between1And3",
        key_skills=["i love python"],
        position="Updated Position",
        location="St. Petersburg",
    )
    assert is_success_response(response)
    assert response.json() == IsPartialDict(
        position="Updated Position",
        location="St. Petersburg",
        about_me="Updated about me",
        key_skills=["i love python"],
        experience_type="between1And3",
        experience=[],
        education=[],
        projects=[],
    )


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.create_resume(
        access_token=access_token,
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )
    resume_id = response.json()["resume_id"]
    response = await test_api_gateway.edit_resume(
        access_token="...",
        resume_id=resume_id,
        about_me="Updated about me",
        experience_type="between1And3",
        key_skills=["i love python"],
        position="Updated Position",
    )
    assert is_unauthorized_response(response)


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)
    access_token = response_sign_up.json()["access_token"]

    response = await test_api_gateway.edit_resume(
        access_token=access_token,
        resume_id=str(uuid7()),
        about_me="Updated about me",
        experience_type="between1And3",
        key_skills=["i love python"],
        position="Updated Position",
    )
    assert is_not_found_response(response)


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

    response_sign_up = await test_api_gateway.sign_up_email(unique_email, DEFAULT_PASSWORD)

    response = await test_api_gateway.create_resume(
        access_token=response_sign_up.json()["access_token"],
        about_me="About me",
        experience_type="noExperience",
        key_skills=["i love lisp", "i love rust"],
        position="Position",
        location="Moscow",
    )

    response_other_sign_up = await test_api_gateway.sign_up_email("f" + unique_email, DEFAULT_PASSWORD)

    response = await test_api_gateway.edit_resume(
        access_token=response_other_sign_up.json()["access_token"],
        resume_id=response.json()["resume_id"],
        about_me="Updated about me",
        experience_type="between1And3",
        key_skills=["i love python"],
        position="Updated Position",
    )

    assert is_forbidden_response(response)
