#!/usr/bin/env python3
"""
Session state store — persistent playback state.

Stored as JSON in ``~/.local/share/neo-pod-desktop/session.json``.
Replaces the ``[Playback]`` section of config.ini — session state
(user's last track, position, volume, playback mode) is user data,
not configuration.
"""

import json
import logging
import os
from typing import Any

from xdg_base import xdg_data_path

logger = logging.getLogger(__name__)

_SESSION_FILE = "session.json"


class SessionStore:
    def __init__(self, path: str | None = None):
        self._path = path or os.path.join(xdg_data_path(), _SESSION_FILE)
        self._data: dict[str, Any] = {}
        self._load()

    # ── load / save ────────────────────────────────────────────────────

    def _load(self) -> None:
        if not os.path.exists(self._path):
            return
        try:
            with open(self._path, "r", encoding="utf-8") as f:
                self._data = json.load(f)
        except (json.JSONDecodeError, OSError) as exc:
            logger.warning("Failed to load session: %s", exc)
            self._data = {}

    def save(self) -> None:
        tmp = self._path + ".tmp"
        try:
            os.makedirs(os.path.dirname(self._path), exist_ok=True)
            with open(tmp, "w", encoding="utf-8") as f:
                json.dump(self._data, f, ensure_ascii=False)
            os.replace(tmp, self._path)
        except OSError as exc:
            logger.warning("Failed to save session: %s", exc)

    # ── typed accessors ────────────────────────────────────────────────

    def get_str(self, key: str, fallback: str = "") -> str:
        return str(self._data.get(key, fallback))

    def get_int(self, key: str, fallback: int = 0) -> int:
        return int(self._data.get(key, fallback))

    def get_bool(self, key: str, fallback: bool = False) -> bool:
        v = self._data.get(key, fallback)
        if isinstance(v, bool):
            return v
        return str(v).lower() in ("true", "1", "yes")

    def set(self, key: str, value: Any) -> None:
        self._data[key] = value

    # ── migrations ─────────────────────────────────────────────────────

    def migrate_from_config(self, config_loader: Any) -> None:
        """Import ``[Playback]`` section from the old config loader."""
        keys = [
            "last_track_path", "last_position_ms", "last_volume",
            "last_playing", "shuffle_active", "repeat_mode",
        ]
        changed = False
        for k in keys:
            if k not in self._data:
                v = config_loader.get("Playback", k, fallback="")
                self.set(k, v)
                changed = True
        if changed:
            self.save()
            # Wipe old Playback section so it isn't read again.
            if config_loader.config.has_section("Playback"):
                config_loader.config.remove_section("Playback")
                config_loader.save()
            logger.info("Migrated playback state from config.ini to session.json")
