"""Named connection pool with persistent session IDs.

Each named connection targets a different MCP endpoint (Hub, bundle, different
workspace/server). Session files store only the Mcp-Session-Id and connection
metadata — never tool lists or discovery data.
"""

import json
import logging
import os
from dataclasses import dataclass, asdict
from datetime import datetime, timezone
from pathlib import Path

from mcpbundles.config import CONFIG_DIR

logger = logging.getLogger(__name__)

SESSIONS_DIR = CONFIG_DIR / "sessions"


@dataclass
class ConnectionInfo:
    name: str
    url: str
    endpoint: str
    workspace_id: str | None
    session_id: str | None
    is_default: bool
    created_at: str

    @property
    def display_target(self) -> str:
        from urllib.parse import urlparse
        parsed = urlparse(self.url)
        return f"{parsed.hostname or self.url}{self.endpoint}"


class ConnectionManager:
    """Manage multiple named MCP connections with persistent session IDs."""

    def __init__(self) -> None:
        SESSIONS_DIR.mkdir(parents=True, exist_ok=True)

    def _path(self, name: str) -> Path:
        return SESSIONS_DIR / f"{name}.json"

    def list_connections(self) -> list[ConnectionInfo]:
        conns: list[ConnectionInfo] = []
        if not SESSIONS_DIR.exists():
            return conns
        for f in sorted(SESSIONS_DIR.glob("*.json")):
            try:
                data = json.loads(f.read_text())
                conns.append(ConnectionInfo(**data))
            except Exception:
                logger.warning("Corrupt session file: %s", f)
        return conns

    def get(self, name: str) -> ConnectionInfo | None:
        path = self._path(name)
        if not path.exists():
            return None
        try:
            return ConnectionInfo(**json.loads(path.read_text()))
        except Exception:
            return None

    def get_default(self) -> ConnectionInfo | None:
        for conn in self.list_connections():
            if conn.is_default:
                return conn
        conns = self.list_connections()
        return conns[0] if conns else None

    def create(
        self,
        name: str,
        url: str,
        endpoint: str = "/hub/",
        workspace_id: str | None = None,
        is_default: bool = False,
    ) -> ConnectionInfo:
        if is_default:
            self._clear_default()
        conn = ConnectionInfo(
            name=name,
            url=url,
            endpoint=endpoint,
            workspace_id=workspace_id,
            session_id=None,
            is_default=is_default,
            created_at=datetime.now(timezone.utc).isoformat(),
        )
        self._save(conn)
        return conn

    def remove(self, name: str) -> bool:
        path = self._path(name)
        if path.exists():
            path.unlink()
            return True
        return False

    def remove_all(self) -> int:
        count = 0
        for f in SESSIONS_DIR.glob("*.json"):
            f.unlink()
            count += 1
        return count

    def save_session_id(self, name: str, session_id: str) -> None:
        conn = self.get(name)
        if conn:
            conn.session_id = session_id
            self._save(conn)

    def invalidate_session(self, name: str) -> None:
        conn = self.get(name)
        if conn:
            conn.session_id = None
            self._save(conn)

    def set_default(self, name: str) -> bool:
        conn = self.get(name)
        if not conn:
            return False
        self._clear_default()
        conn.is_default = True
        self._save(conn)
        return True

    def _clear_default(self) -> None:
        for conn in self.list_connections():
            if conn.is_default:
                conn.is_default = False
                self._save(conn)

    def _save(self, conn: ConnectionInfo) -> None:
        path = self._path(conn.name)
        path.write_text(json.dumps(asdict(conn), indent=2))
        path.chmod(0o600)
