# -*- coding: utf-8 -*-
# type: ignore
from __future__ import annotations

import http
import urllib.parse
import uuid

from django.test import Client
from django.urls import reverse
import pytest
from pytest_django import asserts


@pytest.fixture
def auth_key():
    return str(uuid.uuid4())


@pytest.mark.django_db
def test_ok(authenticated_client: Client,
            auth_key,
            extension_auth_source_extension,
            extension_auth_session_token,
            ):
    # Given
    session = authenticated_client.session
    session['extension_source'] = extension_auth_source_extension
    session['extension_session_token'] = extension_auth_session_token
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
            'auth_key': auth_key,
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.OK

    assert 'extension_source' not in authenticated_client.session
    assert 'extension_session_token' not in authenticated_client.session

    asserts.assertTemplateUsed(
        result, 'ui/integrations/extension/post_authenticate.html',
    )

    assert result.context[0]['app_redirect_url'] is None


@pytest.mark.parametrize(
    'source_fixture_name,expected_app_redirect_url_scheme',
    [
        ('extension_auth_source_desktop', 'hotpocket-desktop'),
        ('extension_auth_source_mobile', 'hotpocket-mobile'),
    ],
)
@pytest.mark.django_db
def test_ok_with_source(source_fixture_name,
                        expected_app_redirect_url_scheme,
                        request: pytest.FixtureRequest,
                        authenticated_client: Client,
                        auth_key,
                        extension_auth_session_token,
                        ):
    # Given
    source = request.getfixturevalue(source_fixture_name)

    session = authenticated_client.session
    session['extension_source'] = source
    session['extension_session_token'] = extension_auth_session_token
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
            'auth_key': auth_key,
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.OK
    assert result.context[0]['app_redirect_url'] is not None

    app_redirect_url = result.context[0]['app_redirect_url']

    parsed_app_redirect_url = urllib.parse.urlsplit(app_redirect_url)
    assert parsed_app_redirect_url.scheme == expected_app_redirect_url_scheme
    assert parsed_app_redirect_url.netloc == 'post-authenticate'
    assert parsed_app_redirect_url.path == '/'

    parsed_app_redirect_url_query = urllib.parse.parse_qs(parsed_app_redirect_url.query)
    assert parsed_app_redirect_url_query['session_token'] == [extension_auth_session_token]
    assert parsed_app_redirect_url_query['auth_key'] == [auth_key]


@pytest.mark.django_db
def test_auth_key_not_request(authenticated_client: Client,
                              extension_auth_source_extension,
                              extension_auth_session_token,
                              ):
    # Given
    session = authenticated_client.session
    session['extension_source'] = extension_auth_source_extension
    session['extension_session_token'] = extension_auth_session_token
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN


@pytest.mark.django_db
def test_source_not_in_session(authenticated_client: Client,
                               extension_auth_session_token,
                               auth_key,
                               ):
    # Given
    session = authenticated_client.session
    session['extension_session_token'] = extension_auth_session_token
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
            'auth_key': auth_key,
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN


@pytest.mark.django_db
def test_session_token_in_session(authenticated_client: Client,
                                  extension_auth_source_extension,
                                  auth_key,
                                  ):
    # Given
    session = authenticated_client.session
    session['extension_source'] = extension_auth_source_extension
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
            'auth_key': auth_key,
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN


@pytest.mark.django_db
def test_auth_key_mismatch(authenticated_client: Client, auth_key):
    # Given
    session = authenticated_client.session
    session['extension_auth_key'] = auth_key
    session.save()

    # When
    result = authenticated_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
        data={
            'auth_key': 'thisisntright',
        },
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN


@pytest.mark.django_db
def test_inactive_account(inactive_account_client: Client):
    # When
    result = inactive_account_client.get(
        reverse('ui.integrations.extension.post_authenticate'),
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN


@pytest.mark.django_db
def test_anonymous(client: Client):
    # When
    result = client.get(
        reverse('ui.integrations.extension.post_authenticate'),
    )

    # Then
    assert result.status_code == http.HTTPStatus.FORBIDDEN
