from __future__ import annotations

import os
import re
from pathlib import Path
from typing import Dict, List, Mapping, Optional

import yaml

from .model import Book, parse_book


def load_book(path: Path) -> Book:
    with open(path, "r", encoding="utf-8") as f:
        data = yaml.safe_load(f)
    if not isinstance(data, dict):
        raise ValueError("Book YAML must be a mapping/object at the top level.")
    return parse_book(data)


def parse_vars_kv(items: List[str]) -> Dict[str, str]:
    out: Dict[str, str] = {}
    for item in items:
        if "=" not in item:
            raise ValueError(f"Invalid var {item!r}. Expected KEY=VALUE.")
        k, v = item.split("=", 1)
        k = k.strip()
        if not k:
            raise ValueError(f"Invalid var {item!r}. KEY cannot be empty.")
        out[k] = v
    return out


def parse_vars_env(s: Optional[str]) -> List[str]:
    """
    Parse env var IAC_VARS:
      - comma-separated: "k=v,k2=v2"
      - whitespace/newline-separated: "k=v k2=v2"
    """
    if not s:
        return []
    parts: List[str] = []
    for chunk in re.split(r"[,\n\r\t ]+", s.strip()):
        if chunk:
            parts.append(chunk)
    return parts


def merge_vars(
    book_vars: Dict[str, str], *, vars_env: Optional[str], vars_cli: List[str]
) -> Dict[str, str]:
    """
    Precedence:
      book.vars < IAC_VARS < IAC_VAR_* env overrides < repeated --var
    """
    merged = dict(book_vars)
    env_items = parse_vars_env(vars_env)
    merged.update(parse_vars_kv(env_items))
    merged.update(_parse_prefixed_vars(os.environ))
    merged.update(parse_vars_kv(vars_cli))
    return merged


def _parse_prefixed_vars(env: Mapping[str, str]) -> Dict[str, str]:
    out: Dict[str, str] = {}
    prefix = "IAC_VAR_"
    for k, v in env.items():
        if not k.startswith(prefix):
            continue
        name = k[len(prefix) :]
        if not name:
            continue
        # IAC_VAR_FOO_BAR -> foo_bar
        norm = name.lower()
        out[norm] = v
    return out
