from urllib.parse import urlencode

import django_tables2
import jdatetime
from django.core.paginator import Paginator, Page
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext_lazy as _
from django_tables2 import A
from django_tables2.columns.linkcolumn import BaseLinkColumn
from django_tables2.rows import BoundRow

from utils import number_convertor_to_milion
from utils.templatetags.common import l10n_date_custom


class CounterColumn(django_tables2.Column):
    empty_values = ()

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('verbose_name', _('Row'))
        kwargs['orderable'] = False
        shrink = kwargs.pop('shrink', True)
        # kwargs.setdefault('exclude_from_export', True)
        super().__init__(*args, **kwargs)
        attrs = self.attrs
        attrs.setdefault('th', {})
        attrs['th'].setdefault('class', '')
        if shrink:
            attrs['th']['class'] += ' shrink'
        attrs['th']['class'] += ' text-center'
        attrs.setdefault('td', {})
        attrs['td'].setdefault('class', '')
        attrs['td']['class'] += 'text-center'

    def render(self, record, table: django_tables2.Table, bound_row: BoundRow, **kwargs):
        try:
            page: Page = table.page
            paginator: Paginator = table.paginator
            counter_shift = 1 + (page.number - 1) * paginator.per_page
        except AttributeError:  # '...Table' object has no attribute 'page'
            counter_shift = 1
        return bound_row.row_counter + counter_shift


class PriceColumn(django_tables2.Column):
    def __init__(self, *args, ltr=True, **kwargs):
        super().__init__(*args, **kwargs)
        self.attrs.setdefault('td', {})
        self.attrs.setdefault('th', {})
        self.attrs.setdefault('tf', {})
        self.attrs['td'].setdefault('class', '')
        self.attrs['th'].setdefault('class', '')
        self.attrs['tf'].setdefault('class', '')
        if 'text-' not in self.attrs['td']['class']:
            self.attrs['td']['class'] = (self.attrs['td']['class'] + ' text-center').strip()
            self.attrs['th']['class'] = (self.attrs['th']['class'] + ' text-center').strip()
            self.attrs['tf']['class'] = (self.attrs['tf']['class'] + ' text-center').strip()
        if ltr:
            self.attrs['td'].setdefault('dir', 'ltr').strip()
            self.attrs['th'].setdefault('dir', 'ltr').strip()
            self.attrs['tf'].setdefault('dir', 'ltr').strip()

    def render(self, value):
        if isinstance(value, int) or isinstance(value, float):
            self.attrs['td']['title'] = f'{round(value, 2):,}'
            return number_convertor_to_milion(value)
        return '---'


class SimpleSeparatorColumn(PriceColumn):
    def render(self, value):
        if isinstance(value, int) or isinstance(value, float):
            self.attrs['td']['title'] = f'{round(value, 2):,}'
            return '{:,}'.format(value)
        return '---'


class PricePercentageColumn(PriceColumn):
    def render(self, value):
        if isinstance(value, dict):
            self.attrs['td']['title'] = f"{value.get('value', 0):,}"
            if 'text-' not in self.attrs['td']['class']:
                self.attrs['td']['class'] = 'rtl-number'
            record_value = value.get('value', 0)
            percentage = value.get('percentage', 0)
            return mark_safe(f'<span>{number_convertor_to_milion(record_value)}({round(percentage, 2)}%)</span>')
        return '---'


class ColorPricePercentageColumn(PriceColumn):
    def render(self, value):
        if isinstance(value, dict):
            self.attrs['td']['title'] = f"{value.get('value', 0):,}"
            if 'text-' not in self.attrs['td']['class']:
                self.attrs['td']['class'] = 'rtl-number'
            color = 'red'
            record_value = value.get('value', 0)
            percentage = value.get('percentage', 0)
            blue_value = value.get('blue_value', 20)
            if 0 < percentage <= blue_value:
                color = 'green'
            if blue_value < percentage:
                color = 'blue'
            return mark_safe(f'<span style="color:{color};">'
                             f'{number_convertor_to_milion(record_value)}({round(percentage, 2)}%)'
                             f'</span>')
        return '---'


class LeadgeneratorTimeColumn(django_tables2.Column):
    def render(self, value):
        return l10n_date_custom(value, 'Y-m-d -- H:i:s')


class LeadgeneratorDateColumn(django_tables2.Column):
    language = None

    def __init__(self, *args, **kwargs):
        self.language = kwargs.pop('language', None)
        super().__init__(*args, **kwargs)

    def render(self, value):
        if self.language == 'persian':
            return jdatetime.datetime.fromgregorian(datetime=value).strftime('%Y-%m-%d')
        else:
            return l10n_date_custom(value, 'Y-m-d')


class ButtonColumn(BaseLinkColumn):
    def __init__(self, text, css_class='', *args, **kwargs):
        kwargs.setdefault('orderable', False)
        kwargs.setdefault('accessor', 'id')
        kwargs.setdefault('attrs', {})
        if kwargs['attrs'] is None:
            kwargs['attrs'] = {}
        attrs = kwargs['attrs']

        attrs.setdefault('a', {})
        attrs['a'].setdefault('class', '')
        attrs['a']['class'] = \
            '{} {} {}'.format(attrs['a']['class'], 'btn small expanded mdi', css_class).strip()

        attrs = kwargs['attrs']
        attrs.setdefault('th', {})
        attrs['th'].setdefault('class', '')
        attrs['th']['class'] += 'shrink'

        attrs = kwargs['attrs']
        attrs.setdefault('td', {})
        attrs['td'].setdefault('class', '')
        attrs['td']['class'] += 'shrink'

        super().__init__(*args, text=text, **kwargs)

    @property
    def header(self):
        return ' '


def resolve_accessors(kwargs, record):
    result = {}
    for (k, v) in kwargs.items():
        if isinstance(v, A):
            v = v.resolve(record)
        result[k] = v
    return result


def remove_optional_kwargs(kwargs):
    """
    Get a copy of kwargs with None values removed. specially for optional url paramenters.
    """
    res = {}
    for (k, v) in kwargs.items():
        if v is not None:
            res[k] = v
    return res


def _create_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    query = kwargs.pop('query', {})
    inline = kwargs.pop('inline', None)
    if inline:
        query['inline'] = 't'

    if callable(viewname):
        def linkify(record):
            return reverse(
                viewname(record),
                kwargs=remove_optional_kwargs(resolve_accessors(kwargs, record))
            ) + (('?' + urlencode(resolve_accessors(query, record))) if query else '')

    elif query:
        def linkify(record):
            return reverse(
                viewname,
                kwargs=remove_optional_kwargs(resolve_accessors(kwargs, record))
            ) + ('?' + urlencode(resolve_accessors(query, record)))

    else:
        linkify = {'viewname': viewname, 'kwargs': kwargs}

    return ButtonColumn(text, css_class, attrs=attrs, linkify=linkify, exclude_from_export=True)


def default_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    return _create_button(text, viewname, css_class='default ' + css_class, attrs=attrs, **kwargs)


def primary_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    return _create_button(text, viewname, css_class='btn-primary ' + css_class, attrs=attrs, **kwargs)


def secondary_button(text, viewname, *, css_class='', attrs=None, dim=False, **kwargs):
    btn_color = 'btn-secondary '
    if dim:
        btn_color = 'btn-outline-secondary '
    return _create_button(text, viewname, css_class=btn_color + css_class, attrs=attrs, **kwargs)


def warning_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    return _create_button(text, viewname, css_class='btn-warning ' + css_class, attrs=attrs, **kwargs)


def danger_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    return _create_button(text, viewname, css_class='btn-danger ' + css_class, attrs=attrs, **kwargs)


def info_button(text, viewname, *, css_class='', attrs=None, **kwargs):
    return _create_button(text, viewname, css_class='btn-info ' + css_class, attrs=attrs, **kwargs)


def success_button(text, viewname, *, css_class='', attrs=None, green=False, **kwargs):
    btn_color = 'btn-success '
    if green:
        btn_color = 'btn-green '
    return _create_button(text, viewname, css_class=btn_color + css_class, attrs=attrs, **kwargs)
