from django import template
from django.template.defaultfilters import stringfilter
from utils.models import SystemSetting
from decimal import Decimal

register = template.Library()

@register.filter
def regroup_by(queryset, field):
    """Group a queryset by a field and return a dictionary of lists"""
    result = {}
    for item in queryset:
        key = getattr(item, field)
        if key not in result:
            result[key] = []
        result[key].append(item)
    return result

@register.filter
def get_setting(settings_dict, key):
    """Get a setting value from a dictionary/queryset/list of settings.

    - If `settings_dict` is falsy, fall back to the SystemSetting DB lookup.
    - Support iterables of model instances, dicts, or (key, value, ...) tuples.
    - If the key isn't found in the iterable, fall back to DB lookup so templates
      still show configured defaults even if the queryset was empty.
    """
    if not settings_dict:
        return SystemSetting.get_setting(key, '')

    for setting in settings_dict:
        # Model instance with .key/.value
        if hasattr(setting, 'key') and hasattr(setting, 'value'):
            if setting.key == key:
                return setting.value

        # Dict-like object
        if isinstance(setting, dict):
            if setting.get('key') == key:
                return setting.get('value', '')

        # Tuple/list like (key, value, ...)
        try:
            if isinstance(setting, (list, tuple)) and len(setting) >= 2:
                if setting[0] == key:
                    return setting[1]
        except Exception:
            pass

    # Not found in provided iterable -> fallback to DB lookup
    return SystemSetting.get_setting(key, '')

@register.filter
def get_item(dictionary, key):
    """Get an item from a dictionary"""
    return dictionary.get(key, None) 

@register.filter
def divide(value, arg):
    """Divides the value by the argument"""
    try:
        if not value or not arg:
            return 0
        return Decimal(str(value)) / Decimal(str(arg))
    except (ValueError, TypeError, ZeroDivisionError):
        return 0

@register.filter
def multiply(value, arg):
    """Multiplies the value by the argument"""
    try:
        if not value or not arg:
            return 0
        return Decimal(str(value)) * Decimal(str(arg))
    except (ValueError, TypeError):
        return 0

@register.filter
def sub(value, arg):
    """Subtracts the argument from the value"""
    try:
        if not value or not arg:
            return 0
        return Decimal(str(value)) - Decimal(str(arg))
    except (ValueError, TypeError):
        return 0

@register.filter
def percentage(value, decimals=1):
    """Formats a value as a percentage with specified decimal places"""
    try:
        if not value:
            return '0%'
        return f"{float(value):.{decimals}f}%"
    except (ValueError, TypeError):
        return '0%'

@register.filter
def replace(value, arg=None):
    """Replace occurrences of a substring in a string. Usage: {{ value|replace:"old:new" }} or {{ value|replace }}"""
    try:
        if arg and ':' in str(arg):
            old, new = str(arg).split(':', 1)
            return str(value).replace(old, new)
        return str(value).replace('_', ' ')
    except (ValueError, AttributeError):
        return value