import json
import math
import os
import random
from pathlib import Path

import numpy as np
import yaml


def load_config(path):
    with open(path, "r", encoding="utf-8") as f:
        return yaml.safe_load(f)


def ensure_dirs(root):
    root = Path(root)
    dirs = {name: root / name for name in ("data", "parameters", "results", "figures")}
    for directory in dirs.values():
        directory.mkdir(parents=True, exist_ok=True)
    return dirs


def save_json(data, path):
    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


def load_json(path):
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)


def seeded_rng(seed):
    random.seed(seed)
    np.random.seed(seed)
    return np.random.default_rng(seed)


def clamp(value, low, high):
    return max(low, min(high, value))


def lognormal_params_from_mean_cv(mean, cv):
    mean = max(float(mean), 1e-6)
    cv = max(float(cv), 1e-6)
    sigma2 = math.log(cv * cv + 1.0)
    sigma = math.sqrt(sigma2)
    mu = math.log(mean) - sigma2 / 2.0
    return mu, sigma


def sample_lognormal(rng, mean, cv, minimum=1.0):
    mu, sigma = lognormal_params_from_mean_cv(mean, cv)
    return max(minimum, float(rng.lognormal(mu, sigma)))


def env(name, default=None):
    value = os.environ.get(name)
    return default if value in (None, "") else value

