import yaml

from schedint.core.storage import (
    OverrideWindow,
    Request,
    _parse_utc,
    build_request,
)


class RequestFormatError(Exception):
    pass


def load_request_from_yaml(path: str) -> Request:
    with open(path, "r", encoding="utf-8") as f:
        data = yaml.safe_load(f)

    if not isinstance(data, dict):
        raise RequestFormatError("Request YAML must be a mapping")

    source = data.get("source")
    reason = data.get("reason")
    overrides_raw = data.get("overrides")

    if not isinstance(source, str) or not source:
        raise RequestFormatError("Source must be a non-empty string")

    if not isinstance(overrides_raw, dict) or not overrides_raw:
        raise RequestFormatError("overrides must be a non-empty mapping")

    overrides = {}

    for key, block in overrides_raw.items():
        if not isinstance(block, dict):
            raise RequestFormatError(f"overrides.{key} must be a mapping")

        value = block.get("value")
        start = _parse_utc(block.get("start_time"))
        end = _parse_utc(block.get("end_time"))

        overrides[key] = OverrideWindow(
            value=value,
            start=start,
            end=end,
        )

    stars_ow = overrides.get("stars")
    cadence_ow = overrides.get("cadence")

    stars_active = stars_ow is not None and stars_ow.value is not None
    cadence_active = cadence_ow is not None and cadence_ow.value is not None

    if stars_active and cadence_active:
        raise RequestFormatError(
            "Cannot set both 'stars' and 'cadence' with non-null values in the same request"
        )

    return build_request(
        source=source,
        overrides=overrides,
        reason=reason,
    )
