from __future__ import annotations

import json
from dataclasses import dataclass
from pathlib import Path

from app_config import APP_DIR


@dataclass(frozen=True)
class JobDefinition:
    job_id: str
    schedule: str
    input_date_policy: str
    dependencies: tuple[str, ...]
    lock_key: str
    timeout_seconds: int
    max_attempts: int
    output_version: str


class JobRegistry:
    def __init__(self, definitions: tuple[JobDefinition, ...]) -> None:
        self.definitions = definitions
        self._by_id = {item.job_id: item for item in definitions}
        if len(self._by_id) != len(definitions):
            raise ValueError("Background job IDs must be unique")

    @classmethod
    def load(cls, path: Path | None = None) -> "JobRegistry":
        config_path = path or APP_DIR / "config" / "jobs.config.json"
        payload = json.loads(config_path.read_text(encoding="utf-8"))
        definitions = tuple(
            JobDefinition(
                job_id=str(item["id"]),
                schedule=str(item["schedule"]),
                input_date_policy=str(item["input_date_policy"]),
                dependencies=tuple(str(value) for value in item.get("dependencies") or []),
                lock_key=str(item["lock_key"]),
                timeout_seconds=max(1, int(item["timeout_seconds"])),
                max_attempts=max(1, int(item["max_attempts"])),
                output_version=str(item["output_version"]),
            )
            for item in payload.get("jobs") or []
        )
        if not definitions:
            raise ValueError("Background job registry is empty")
        return cls(definitions)

    def get(self, job_id: str) -> JobDefinition:
        try:
            return self._by_id[job_id]
        except KeyError as exc:
            raise ValueError(f"Background job is not registered: {job_id}") from exc
