import json
from datetime import datetime, timezone
from pathlib import Path

SESSION_STATE_FILE = Path(__file__).resolve().parents[2] / "browser_data" / "session_state.json"


class SessionStore:
    """Tracks login state in a small JSON file (cookies stay in browser_data/)."""

    def __init__(self, path: Path = SESSION_STATE_FILE):
        self.path = path
        self.path.parent.mkdir(parents=True, exist_ok=True)

    def read(self) -> dict:
        if not self.path.exists():
            return {"logged_in": False}
        try:
            return json.loads(self.path.read_text(encoding="utf-8"))
        except json.JSONDecodeError:
            return {"logged_in": False}

    def write(self, data: dict) -> None:
        self.path.write_text(
            json.dumps(data, indent=2),
            encoding="utf-8",
        )

    def mark_logged_in(self, url: str) -> None:
        data = self.read()
        data["logged_in"] = True
        data["last_url"] = url
        data["updated_at"] = datetime.now(timezone.utc).isoformat()
        self.write(data)

    def get_exchanges_url(self) -> str | None:
        return self.read().get("exchanges_url")

    def set_exchanges_url(self, url: str) -> None:
        data = self.read()
        data["exchanges_url"] = url
        self.write(data)

    def mark_logged_out(self) -> None:
        self.write(
            {
                "logged_in": False,
                "last_url": None,
                "updated_at": datetime.now(timezone.utc).isoformat(),
            }
        )

    def get_account_holder_name(self) -> str | None:
        return self.read().get("account_holder_name")

    def set_account_holder_name(self, name: str) -> None:
        data = self.read()
        data["account_holder_name"] = name
        self.write(data)

    def is_marked_logged_in(self) -> bool:
        return bool(self.read().get("logged_in"))

    def get_storage_warning(
        self, *, max_age_seconds: int = 1800, team_id: str | None = None
    ) -> dict | None:
        """Return cached storage warning if still fresh (default 30 minutes)."""
        data = self.read()
        warning = data.get("storage_warning")
        if not warning:
            return None

        wanted = str(team_id or "").strip()
        cached_team = str(data.get("storage_warning_team_id") or warning.get("team_id") or "").strip()
        # When a team is requested, only reuse cache for that same team.
        if wanted and cached_team and wanted != cached_team:
            return None

        if max_age_seconds < 0:
            return warning
        updated_at = data.get("storage_warning_at")
        if not updated_at:
            return warning
        try:
            ts = datetime.fromisoformat(updated_at)
            if ts.tzinfo is None:
                ts = ts.replace(tzinfo=timezone.utc)
            age = (datetime.now(timezone.utc) - ts).total_seconds()
            if age > max_age_seconds:
                return None
        except (TypeError, ValueError):
            return warning
        return warning

    def get_storage_warning_cached(self, team_id: str | None = None) -> dict | None:
        """Return cached storage warning regardless of age (for sidebar display)."""
        return self.get_storage_warning(max_age_seconds=-1, team_id=team_id)

    def set_storage_warning(self, warning: dict, team_id: str | None = None) -> None:
        data = self.read()
        tid = str(team_id or warning.get("team_id") or "").strip() or None
        payload = dict(warning or {})
        if tid:
            payload["team_id"] = tid
        data["storage_warning"] = payload
        data["storage_warning_team_id"] = tid
        data["storage_warning_at"] = datetime.now(timezone.utc).isoformat()
        self.write(data)

    def clear_storage_warning(self) -> None:
        data = self.read()
        data.pop("storage_warning", None)
        data.pop("storage_warning_team_id", None)
        data.pop("storage_warning_at", None)
        self.write(data)


session_store = SessionStore()
