import json
from typing import List, Optional
from urllib.parse import urlencode

from django.contrib.auth import get_user_model

from ..auth.base import BaseAmmoAuth

User = get_user_model()


REQUEST_TEMPLATE = '{method} {path} HTTP/1.0'
CONTENT_LENGTH = 'Content-Length: {body_length}'


def build_request(
    path: str,
    method: str,
    tag: str = '',
    headers: Optional[List[str]] = None,
    body: Optional[str] = None,
    query_params: Optional[dict] = None,
) -> str:
    """Builds request data for ammo."""

    if query_params:
        path += "?" + urlencode(query_params)
    request = REQUEST_TEMPLATE.format(method=method, path=path)
    if headers is None:
        headers = []
    if body is not None:
        headers += [CONTENT_LENGTH.format(body_length=len(body))]
        result = ['', body]
    else:
        result = []
    result = '\r\n'.join([request] + headers + result)
    return '\n'.join([f'{str(len(result))} {tag}', result, '', ''])


class BaseAmmo:
    URL = None
    TAG = ''
    METHOD = None
    DEFAULT_HEADERS = [
        'Accept: */*',
        'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
        'Accept-Encoding: gzip,deflate,br',
        'Content-Type: application/json',
        'Connection: keep-alive',
    ]
    DEFAULT_HOST_HEADER_TEMPLATE = 'Host: {host}'

    def __init__(self, host: str, payload: dict, auth: Optional[BaseAmmoAuth]):
        self.auth = auth
        self.payload = payload
        self.host = host
        self.body = {}
        self.url_params = {}
        self.query_params = {}
        self.headers = self.DEFAULT_HEADERS + [self.DEFAULT_HOST_HEADER_TEMPLATE.format(host=self.host)]
        if self.auth:
            self.auth(ammo=self)

    def get_url_params(self) -> dict:
        return self.payload

    def get_query_params(self) -> dict:
        return self.query_params

    def get_body(self) -> dict:
        return self.body

    def get_headers(self) -> List[str]:
        return self.headers

    def generate(self) -> str:
        return build_request(
            path=self.URL.format(**self.get_url_params()),
            method=self.METHOD,
            tag=self.TAG,
            headers=self.get_headers(),
            body=json.dumps(self.get_body()),
            query_params=self.get_query_params(),
        )
