"""Read-side helpers other apps use instead of hardcoding their own industry lists."""
import json

from django.core.cache import cache

from .models import Industry, SubIndustry

CACHE_KEY = 'taxonomy:active-tree'
CACHE_SECONDS = 60 * 30
NOT_SURE = 'Not Sure / Other'


def active_tree():
    """{'Industry name': ['Sub 1', 'Sub 2', ...]} for active industries/sub-industries, cached."""
    tree = cache.get(CACHE_KEY)
    if tree is not None:
        return tree
    tree = {}
    subs = SubIndustry.objects.filter(is_active=True, industry__is_active=True).select_related('industry')
    by_industry = {}
    for sub in subs:
        by_industry.setdefault(sub.industry.name, []).append(sub.name)
    for industry in Industry.objects.filter(is_active=True).order_by('sort_order', 'name'):
        tree[industry.name] = by_industry.get(industry.name, [])
    cache.set(CACHE_KEY, tree, CACHE_SECONDS)
    return tree


def clear_cache():
    cache.delete(CACHE_KEY)


def industry_choices(blank_label='Select industry', include_not_sure=True):
    names = list(active_tree().keys())
    choices = [('', blank_label)] + [(n, n) for n in names]
    if include_not_sure and NOT_SURE not in names:
        choices.append((NOT_SURE, NOT_SURE))
    return choices


def sub_industry_choices(industry_name, blank_label='Select sub-industry'):
    return [('', blank_label)] + [(n, n) for n in active_tree().get(industry_name, [])]


def sub_industry_map_json():
    """JSON blob {industry: [sub, ...]} for client-side cascading dropdowns (no AJAX needed)."""
    return json.dumps(active_tree())


def selected_value(form, field_name, fallback=''):
    """The industry a dependent sub-industry field should validate against.

    On a bound (POST) form this must be what the user just submitted, not the
    old saved value on the instance - otherwise picking a new industry and a
    matching sub-industry in the same request fails validation, because the
    sub-industry choices would still be built from the previous industry.
    """
    if form.is_bound:
        return (form.data.get(form.add_prefix(field_name)) or '').strip()
    return (fallback or '').strip()
