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

import logging
import urllib.parse
import uuid

from django import db
from django.core.exceptions import PermissionDenied
from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render
from django.urls import reverse

from hotpocket_backend.apps.ui.constants import AuthSource
from hotpocket_soa.services import AuthKeysService

LOGGER = logging.getLogger(__name__)

SOURCE_TO_REDIRECT_SCHEME = {
    AuthSource.DESKTOP.value: 'hotpocket-desktop',
    AuthSource.MOBILE.value: 'hotpocket-mobile',
}


def authenticate(request: HttpRequest) -> HttpResponse:
    source = request.GET.get(
        'source',
        request.session.get('extension_source', AuthSource.BROWSER_EXTENSION.value),
    )
    session_token = request.GET.get(
        'session_token', request.session.get('extension_session_token', None),
    )

    if source == AuthSource.BROWSER_EXTENSION.value:
        session_token = str(uuid.uuid4())
    elif source in (AuthSource.DESKTOP.value, AuthSource.MOBILE.value):
        assert session_token not in ('', None), 'Session token missing'
    else:
        raise ValueError(f'Unknown source: `{source}`')

    request.session['extension_source'] = source
    request.session['extension_session_token'] = session_token
    request.session.save()

    if request.user.is_anonymous is False:
        with db.transaction.atomic():
            auth_key = AuthKeysService().create(
                account_uuid=request.user.pk,
            )

        return redirect(reverse(
            'ui.integrations.extension.post_authenticate',
            query=[
                ('auth_key', auth_key.key),
            ],
        ))

    return redirect(reverse('ui.accounts.login', query=[
        ('next', reverse('ui.integrations.extension.authenticate')),
    ]))


def post_authenticate(request: HttpRequest) -> HttpResponse:
    try:
        assert request.user.is_anonymous is False, 'Not authenticated'

        auth_key = request.GET.get('auth_key', None)
        assert auth_key is not None, 'Auth key missing'
        source = request.session.get('extension_source', None)
        assert source is not None, 'Source is missing'
        session_token = request.session.get('extension_session_token', None)
        assert session_token is not None, 'Session token is missing'

        app_redirect_url = None
        if source in (AuthSource.DESKTOP.value, AuthSource.MOBILE.value):
            app_redirect_url = urllib.parse.urlunsplit((
                SOURCE_TO_REDIRECT_SCHEME[source],
                'post-authenticate',
                '/',
                urllib.parse.urlencode([
                    ('session_token', session_token),
                    ('auth_key', auth_key),
                ]),
                '',
            ))

        request.session.pop('extension_source')
        request.session.pop('extension_session_token')
        request.session.save()

        return render(
            request,
            'ui/integrations/extension/post_authenticate.html',
            {
                'app_redirect_url': app_redirect_url,
            },
        )
    except AssertionError as exception:
        LOGGER.error(
            'Unable to handle extension authentication: %s',
            exception,
            exc_info=exception,
        )

        raise PermissionDenied('NOPE')
