"""File-backed demo scenarios used by the PoC4 Streamlit screen.

Scenario content is deliberately configuration, not executable routing policy.
Changing this JSON changes only the menu shown to a demo user.
"""

from __future__ import annotations

from dataclasses import dataclass
import json
from pathlib import Path
from typing import Any, Mapping


class ScenarioConfigError(RuntimeError):
    """A safe, user-facing error for invalid scenario configuration."""


@dataclass(frozen=True)
class DemoScenario:
    scenario_id: str
    category: str
    title: str
    question: str

    # Compatibility aliases keep the Streamlit rendering independent from the
    # storage field names and make a future scenario source interchangeable.
    @property
    def question_id(self) -> str:
        return self.scenario_id

    @property
    def text(self) -> str:
        return self.question


def load_demo_scenarios(path: Path) -> tuple[DemoScenario, ...]:
    """Read enabled scenarios and reject malformed or duplicated entries."""

    try:
        payload: Any = json.loads(path.read_text(encoding="utf-8"))
    except (OSError, UnicodeError, ValueError):
        raise ScenarioConfigError(f"질문 시나리오 설정을 읽지 못했습니다: {path}") from None

    raw_scenarios = payload.get("scenarios") if isinstance(payload, Mapping) else None
    if not isinstance(raw_scenarios, list):
        raise ScenarioConfigError("질문 시나리오 설정에 scenarios 배열이 필요합니다.")

    scenarios: list[DemoScenario] = []
    seen_ids: set[str] = set()
    for raw in raw_scenarios:
        if not isinstance(raw, Mapping) or raw.get("enabled", True) is not True:
            continue
        scenario_id = str(raw.get("id") or "").strip().upper()
        category = str(raw.get("category") or "일반").strip()
        title = str(raw.get("title") or "").strip()
        question = str(raw.get("question") or "").strip()
        if not scenario_id or not title or not question:
            raise ScenarioConfigError("각 질문 시나리오에는 id, title, question이 필요합니다.")
        if scenario_id in seen_ids:
            raise ScenarioConfigError(f"중복된 질문 시나리오 ID입니다: {scenario_id}")
        scenarios.append(
            DemoScenario(
                scenario_id=scenario_id,
                category=category,
                title=title,
                question=question,
            )
        )
        seen_ids.add(scenario_id)
    return tuple(scenarios)
