from django.utils.html import format_html

from .urls import admin_change_url, admin_changelist_url


__all__ = 'admin_link_field', 'admin_changelist_link_field',


def admin_link_field(
    attr,
    short_description,
    empty_description='-',
):
    """Decorator used for rendering a link to a related model in
    the admin detail page.
    attr (str):
        Name of the related field.
    short_description (str):
        Name if the field.
    empty_description (str):
        Value to display if the related field is None.
    The wrapped method receives the related object and should
    return the link text.
    Usage:
        @admin_link('credit_card', _('Credit Card'))
        def credit_card_link(self, credit_card):
            return credit_card.name
    """
    def wrap(func):
        def field_func(self, obj):
            related_obj = getattr(obj, attr)
            if related_obj is None:
                return empty_description
            url = admin_change_url(related_obj)
            return format_html(
                '<a href="{}" target="_blank">{}</a>',
                url,
                func(self, related_obj),
            )
        field_func.short_description = short_description
        field_func.allow_tags = True

        return field_func

    return wrap


def admin_changelist_link_field(
    attr,
    short_description,
    empty_description='-',
    query_string=None,
):
    """Decorator used for rendering a link to the list display of
    a related model in the admin detail page.
    attr (str):
        Name of the related field.
    short_description (str):
        Field display name.
    empty_description (str):
        Value to display if the related field is None.
    query_string (function):
        Optional callback for adding a query string to the link.
        Receives the object and should return a query string.
    The wrapped method receives the related object and
    should return the link text.
    Usage:
        @admin_changelist_link('credit_card', _('Credit Card'))
        def credit_card_link(self, credit_card):
            return credit_card.name

        @admin_changelist_link(
            'products',
            _('Products'),
            query_string=lambda c: 'category_id={}'.format(c.pk)
        )
        def products_link(self, products):
            return _('Products')
    """
    def wrap(func):
        def field_func(self, obj):
            related_obj = getattr(obj, attr)

            if related_obj is None:
                return empty_description

            url = admin_changelist_url(related_obj.model)

            if query_string:
                url += '?' + query_string(obj)

            return format_html(
                '<a href="{}" target="_blank">{}</a>',
                url,
                func(self, related_obj),
            )

        field_func.short_description = short_description
        field_func.allow_tags = True

        return field_func

    return wrap
