import json
from pathlib import Path
from typing import Any

from app.config import Settings
from app.errors import ApiError
from app.schemas.camera import Camera, CameraDetail, LiveStream


class CameraService:
    def __init__(self, settings: Settings) -> None:
        self.settings = settings
        self._cameras = self._load_cameras()

    def _load_cameras(self) -> list[CameraDetail]:
        if self.settings.cameras_json:
            return self._parse_cameras_json(self.settings.cameras_json)

        ingestion_cameras = self._load_ingestion_cameras()
        if ingestion_cameras:
            return ingestion_cameras

        return [CameraDetail(id=0, name="Camera 0", webrtc_url="/stream/cam0")]

    def _parse_cameras_json(self, raw_json: str) -> list[CameraDetail]:
        raw = json.loads(raw_json)
        return [CameraDetail.model_validate(item) for item in raw]

    def _load_ingestion_cameras(self) -> list[CameraDetail]:
        if not self.settings.ingestion_config_path:
            return []
        path = Path(self.settings.ingestion_config_path)
        if not path.exists():
            return []
        raw: dict[str, Any] = json.loads(path.read_text())
        video_sources = raw.get("video_sources", [])
        if not isinstance(video_sources, list):
            return []
        return [
            CameraDetail(id=index, name=f"Camera {index}", webrtc_url=f"/stream/cam{index}")
            for index, _source in enumerate(video_sources)
        ]

    async def list_cameras(self) -> list[Camera]:
        return [Camera(id=camera.id, name=camera.name) for camera in self._cameras]

    async def get_camera(self, camera_id: int) -> CameraDetail:
        for camera in self._cameras:
            if camera.id == camera_id:
                return camera
        raise ApiError("camera_not_found", "Camera does not exist", 404)

    async def list_live_streams(self) -> list[LiveStream]:
        return [
            LiveStream(camera_id=camera.id, name=camera.name, webrtc_url=camera.webrtc_url or f"/stream/cam{camera.id}")
            for camera in self._cameras
        ]
