import json
import sys
from pathlib import Path

sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace")

BASE_DIR = Path(__file__).resolve().parent.parent

CAMERAS_FILE = BASE_DIR / "Archivos" / "stage_cameras.json"

STAGES = ("sugerente", "spicy1", "spicy2", "explicit1", "explicit2")
STAGE_LEVEL = {
    "sugerente": "sugerente",
    "spicy1": "spicy",
    "spicy2": "spicy",
    "explicit1": "explicito",
    "explicit2": "explicito",
}
STAGE_DRESS = {
    "sugerente": "dressed",
    "spicy1": "stripping",
    "spicy2": "lingerie",
    "explicit1": "clothed",
    "explicit2": "nude",
}
DEFAULT_STAGE_QUOTAS = {stage: 9 for stage in STAGES}
LEVEL_STAGE_FALLBACK = {
    "sugerente": "sugerente",
    "spicy": "spicy1",
    "explicito": "explicit2",
}
DRESSES = ("dressed", "stripping", "lingerie", "clothed", "nude")
_EXPLICIT1_BLOCKED = frozenset({
    "cum",
    "cum overflow",
    "cum in pussy",
    "cum in mouth",
    "orgasm",
    "after sex",
})

_DRESS_NEGATIVE = {
    "dressed": "nipples, topless",
    "stripping": "nipples, topless",
    "lingerie": "topless, bottomless",
    "clothed": "full nudity",
    "nude": "",
    "auto": "",
}


def load_stage_cameras(path=None, fallback=None):
    fallback = list(fallback or [])
    target = Path(path) if path is not None else CAMERAS_FILE
    result = {stage: list(fallback) for stage in STAGES}
    try:
        data = json.loads(target.read_text(encoding="utf-8-sig"))
    except (OSError, ValueError) as exc:
        print("AVISO: no se pudo leer %s: %s" % (target, exc), file=sys.stderr)
        return result
    if not isinstance(data, dict):
        print("AVISO: %s no contiene un objeto JSON" % target, file=sys.stderr)
        return result
    for stage in STAGES:
        values = data.get(stage)
        if not isinstance(values, list):
            continue
        clean = [value.strip() for value in values
                 if isinstance(value, str) and value.strip()]
        if clean:
            result[stage] = clean
    return result


def parse_stage_quotas(text):
    if text is None:
        return dict(DEFAULT_STAGE_QUOTAS)
    parts = [part.strip() for part in text.split(",")]
    if len(parts) != len(STAGES):
        raise ValueError("se esperaban 5 cuotas de stage")
    values = []
    for part in parts:
        try:
            value = int(part)
        except (TypeError, ValueError):
            raise ValueError("cuota de stage no entera: %r" % part)
        if value < 0:
            raise ValueError("cuota de stage negativa: %r" % part)
        values.append(value)
    return dict(zip(STAGES, values))


def stage_for_record(record):
    stage = record.get("stage")
    if stage in STAGES:
        return stage
    return LEVEL_STAGE_FALLBACK.get(record.get("nivel"), "sugerente")


def stage_allows_pose(stage, pose_line):
    if stage != "explicit1":
        return True
    tags = {part.strip().replace("_", " ").lower()
            for part in str(pose_line or "").split(",") if part.strip()}
    return not (tags & _EXPLICIT1_BLOCKED)


def dress_for_stage(stage, override=None):
    if stage not in STAGES:
        raise ValueError("stage desconocido: %r" % stage)
    if override is not None and override != "auto":
        if override not in DRESSES:
            raise ValueError("dress desconocido: %r" % override)
        return override
    return STAGE_DRESS[stage]


def dress_negative(dress):
    if dress not in _DRESS_NEGATIVE:
        raise ValueError("dress desconocido: %r" % dress)
    return _DRESS_NEGATIVE[dress]


def force_nude_for(dress):
    if dress not in DRESSES and dress != "auto":
        raise ValueError("dress desconocido: %r" % dress)
    if dress == "nude":
        return "always"
    if dress == "auto":
        return "auto"
    return "never"
