import os
from urllib.parse import urlencode

import pytest
from django.conf import settings
from django.urls import reverse
from pytest_docker_tools import container
from rest_framework.test import APIClient

from activate_account.factories import AccountDetailsFactory, AccountFactory
from authentication.constants import SESSION_GRANT_TYPE

# We only modify the database settings for the test suite if TEST_USE_EXTERNAL_DATABASE is not set
# to a non-empty value.
if os.environ.get("TEST_USE_EXTERNAL_DATABASE", "") == "":
    postgres_container = container(
        scope="session",
        image="postgres",
        environment={
            "POSTGRES_USER": "pytest-user",
            "POSTGRES_PASSWORD": "pytest-pass",
            "POSTGRES_DB": "pytest-db",
        },
        ports={
            "5432/tcp": None,
        },
    )

    @pytest.fixture(scope="session")
    def django_db_modify_db_settings(
        django_db_modify_db_settings_parallel_suffix, postgres_container
    ):
        """
        Modify database settings based on the postgres docker container we spun up.
        """
        host, port = postgres_container.get_addr("5432/tcp")
        db_settings = {
            "HOST": host,
            "PORT": port,
            "NAME": "pytest-db",
            "USER": "pytest-user",
            "PASSWORD": "pytest-pass",
        }

        for db_item in settings.DATABASES.values():
            db_item.update(db_settings)
            db_item.get("TEST", {}).update(db_settings)


@pytest.fixture
def account(db):
    return AccountFactory()


@pytest.fixture
def account_details(account):
    return AccountDetailsFactory(account=account)


@pytest.fixture
def api_client():
    return APIClient()


@pytest.fixture
def authenticated_api_client(account, api_client):
    response = api_client.post(
        reverse("knox_login"),
        data=urlencode(
            {
                "grant_type": SESSION_GRANT_TYPE,
                "crsid": account.crsid,
                "code": account.code,
                "date_of_birth": account.date_of_birth.strftime("%Y-%m-%d"),
            }
        ),
        content_type="application/x-www-form-urlencoded",
    )
    return APIClient(headers={"Authorization": f"Bearer {response.json()['access_token']}"})