import sys
from pathlib import Path

import yaml

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

BASE_DIR = Path(__file__).resolve().parent.parent
AFFINITY_FILE = BASE_DIR / "Archivos" / "pose_scene_affinity.yaml"


def load_affinity(path=None):
    target = Path(path) if path is not None else AFFINITY_FILE
    try:
        data = yaml.safe_load(target.read_text(encoding="utf-8-sig"))
    except (OSError, yaml.YAMLError) as exc:
        print("AVISO: no se pudo leer %s: %s" % (target, exc), file=sys.stderr)
        return {"poses": {}}
    if not isinstance(data, dict) or not isinstance(data.get("poses"), dict):
        print("AVISO: %s no contiene 'poses' valido" % target, file=sys.stderr)
        return {"poses": {}}
    return data


def _tags(line):
    return {part.strip().replace("_", " ").lower()
            for part in str(line or "").split(",") if part.strip()}


def _rule_tags(rule, key):
    values = rule.get(key)
    if not isinstance(values, list):
        return []
    return [str(value).strip().replace("_", " ").lower()
            for value in values if str(value).strip()]


def _has_tag(scene_tags, wanted):
    if wanted in scene_tags:
        return True
    for tag in scene_tags:
        if wanted in tag.split():
            return True
    return False


def validate_pose_scene(pose_line, scene_line, affinity=None):
    if affinity is None:
        affinity = load_affinity()
    poses = affinity.get("poses") if isinstance(affinity, dict) else {}
    if not isinstance(poses, dict):
        return []
    rules = {str(key).replace("_", " ").lower(): value
             for key, value in poses.items() if isinstance(value, dict)}
    pose_tags = _tags(pose_line)
    scene_tags = _tags(scene_line)
    warnings = []
    for pose_tag in sorted(pose_tags):
        rule = rules.get(pose_tag)
        if not rule:
            continue
        requires = _rule_tags(rule, "requires")
        missing = [tag for tag in requires if not _has_tag(scene_tags, tag)]
        if missing:
            warnings.append("%s requiere %s en la escena (falta: %s)" %
                            (pose_tag, ", ".join(requires), ", ".join(missing)))
        requires_any = _rule_tags(rule, "requires_any")
        if requires_any and not any(_has_tag(scene_tags, tag)
                                    for tag in requires_any):
            warnings.append("%s requiere soporte/entorno: %s" %
                            (pose_tag, ", ".join(requires_any)))
        conflicts = _rule_tags(rule, "conflicts")
        found = [tag for tag in conflicts if _has_tag(scene_tags, tag)]
        if found:
            warnings.append("%s choca con la escena: %s" %
                            (pose_tag, ", ".join(found)))
    return warnings
