"""Utils app method."""
import logging
import random
import re
import string
from collections import namedtuple

import requests
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.contrib.gis.geos import Point
from django.http.request import HttpRequest
from django.utils.timezone import datetime
from rest_framework import status
from rest_framework.request import Request

logger = logging.getLogger(__name__)


def generate_code(digits=6, string_output=True):
    """Generate random int."""
    max_value = 10 ** digits - 1
    min_value = 10 ** (digits - 1)
    value = random.randint(min_value, max_value)
    return str(value) if string_output else value


def get_token_from_cookies(request):
    """Get access token from request cookies"""
    cookies = request.COOKIES
    if cookies.get('access_token'):
        token = f'Bearer {cookies.get("access_token")}'
        return token.encode()


def get_token_from_request(request):
    """Get access token from request"""
    token = None
    if 'Authorization' in request.headers:
        if isinstance(request, HttpRequest):
            token = request.headers.get('Authorization').split(' ')[::-1][0]
        if isinstance(request, Request):
            token = request.headers.get('Authorization').split(' ')[::-1][0]
    return token


def username_validator(username: str) -> bool:
    """Validate given username"""
    pattern = r'[@,]+'
    if re.search(pattern=pattern, string=username):
        return False
    else:
        return True


def image_path(instance, filename):
    """Determine avatar path method."""
    filename = '%s.jpeg' % generate_code()
    return 'image/%s/%s/%s' % (
        instance._meta.model_name,
        datetime.now().strftime(settings.REST_DATE_FORMAT),
        filename)


def svg_image_path(instance, filename):
    """Determine SVG path method."""
    filename = '%s.svg' % generate_code()
    return 'svg/%s/%s/%s' % (
        instance._meta.model_name,
        datetime.now().strftime(settings.REST_DATE_FORMAT),
        filename)


def get_user_ip(request):
    """Get user ip."""
    meta_dict = request.META
    x_forwarded_for = meta_dict.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = meta_dict.get('REMOTE_ADDR')
    return ip


def generate_string_code(size=64,
                         chars=string.ascii_lowercase + string.ascii_uppercase + string.digits):
    """Generate string code."""
    return ''.join([random.SystemRandom().choice(chars) for _ in range(size)])


def get_contenttype(app_label: str, model: str):
    """Get ContentType instance by app_label and model"""
    qs = ContentType.objects.filter(app_label=app_label, model=model)
    if qs.exists():
        return qs.first()


def image_url_valid(url: str):
    """
    Check if requested URL is valid.
    :param url: string
    :return: boolean
    """
    try:
        assert url.startswith('http')
        response = requests.request('head', url)
    except Exception as e:
        logger.info(f'ConnectionError: {e}')
    else:
        return response.status_code == status.HTTP_200_OK


def absolute_url_decorator(func):
    def get_absolute_image_url(self, obj):
        """Get absolute image url"""
        url_path = func(self, obj)
        if url_path:
            if url_path.startswith('/media/'):
                return f'{settings.MEDIA_URL}{url_path}/'
            else:
                return url_path
    return get_absolute_image_url


def get_point_from_coordinates(latitude: str, longitude: str):
    if latitude and longitude:
        return Point(x=longitude, y=latitude, srid=4326)


def namedtuplefetchall(cursor):
    """Return all rows from a cursor as a namedtuple."""
    desc = cursor.description
    nt_result = namedtuple('Result', [col[0] for col in desc])
    return [nt_result(*row) for row in cursor.fetchall()]


def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]


def transform_into_readable_str(raw_string: str, postfix: str = 'SectionNode'):
    """
    Transform slug into section name, i.e:
    like
    "EffervescentRoseDeSaigneeSectionNode"
    from
    "effervescent-rose-de-saignee"
    """
    re_exp = r'[\w]+'
    result = re.findall(re_exp, raw_string)
    if result:
        return f"{''.join([i.capitalize() for i in result])}"


def section_name_into_index_name(section_name: str):
    """
    Transform slug into section name, i.e:
    like
    "Restaurant"
    from
    "RestaurantSectionNode"
    """
    re_exp = r'[A-Z][^A-Z]*'
    result = re.findall(re_exp, section_name)
    if result:
        return f"{' '.join([word.capitalize() if i == 0 else word for i, word in enumerate(result[:-2])])}"
