import random

ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp'}

_LORA_DEFAULTS = {
    'characters': '/ImageModels/lora/Illustrious/Looks',
    'outfits':    '/ImageModels/lora/Illustrious/Clothing',
    'actions':    '/ImageModels/lora/Illustrious/Poses',
    'styles':     '/ImageModels/lora/Illustrious/Styles',
    'scenes':     '/ImageModels/lora/Illustrious/Backgrounds',
    'detailers':  '/ImageModels/lora/Illustrious/Detailers',
}

_BODY_GROUP_KEYS = ['base', 'head', 'upper_body', 'lower_body', 'hands', 'feet', 'additional']


def clean_html_text(html_raw):
    """Strip HTML tags, scripts, styles, and images from raw HTML, returning plain text."""
    import re
    text = re.sub(r'<script[^>]*>.*?</script>', '', html_raw, flags=re.DOTALL)
    text = re.sub(r'<style[^>]*>.*?</style>', '', text, flags=re.DOTALL)
    text = re.sub(r'<img[^>]*>', '', text)
    text = re.sub(r'<[^>]+>', ' ', text)
    return ' '.join(text.split())


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


def parse_orientation(orientation_str):
    if not orientation_str: return []

    m_count = orientation_str.upper().count('M')
    f_count = orientation_str.upper().count('F')
    total = m_count + f_count

    tags = []

    # Gender counts
    if m_count == 1: tags.append("1boy")
    elif m_count > 1: tags.append(f"{m_count}boys")

    if f_count == 1: tags.append("1girl")
    elif f_count > 1: tags.append(f"{f_count}girls")

    # Relationships/Group type
    if total == 1:
        tags.append("solo")
    elif total > 1:
        if m_count > 0 and f_count > 0:
            tags.append("hetero")
        elif f_count > 1 and m_count == 0:
            tags.append("yuri")
        elif m_count > 1 and f_count == 0:
            tags.append("yaoi")

    return tags


def _resolve_lora_weight(lora_data, override=None):
    """Return effective LoRA weight, randomising between min/max when they differ.

    If *override* is provided it takes absolute precedence (used by the Strengths
    Gallery to pin a specific value for each step).
    """
    if override is not None:
        return float(override)
    weight = float(lora_data.get('lora_weight', 1.0))
    min_w = lora_data.get('lora_weight_min')
    max_w = lora_data.get('lora_weight_max')
    if min_w is not None and max_w is not None:
        min_w, max_w = float(min_w), float(max_w)
        if min_w != max_w:
            weight = random.uniform(min(min_w, max_w), max(min_w, max_w))
    return weight
