"""Exact target paths and service-manager implementations."""

from __future__ import annotations

import subprocess
from dataclasses import dataclass
from pathlib import Path
from typing import Final, Protocol, final

CURRENT_RUNTIME: Final = Path(
    "/home/cube/.hermes/profiles/dualcoachtest/.strict-runtime/6c9c4394-v132/venv"
)
SUCCESSOR_RUNTIME: Final = Path(
    "/home/cube/.hermes/profiles/dualcoachtest/.strict-runtime/066a794d-v150/venv"
)
PROFILE_ROOT: Final = Path("/home/cube/.hermes/profiles/dualcoachtest")
UNIT: Final = Path(
    "/home/cube/.config/systemd/user/hermes-gateway-dualcoachtest.service"
)
DROPIN: Final = Path(
    "/home/cube/.config/systemd/user/"
    + "hermes-gateway-dualcoachtest.service.d/task26-authority.conf"
)


class HostError(RuntimeError):
    """Concrete host boundary failure."""


class Service(Protocol):
    """Synchronous service manager."""

    @property
    def running(self) -> bool: ...

    def stop(self) -> None: ...
    def reload(self) -> None: ...
    def start(self) -> None: ...
    def observe(self) -> dict[str, str]: ...


@final
class DisposableService:
    """Filesystem-test service state machine."""

    def __init__(self) -> None:
        self.running = True
        self.pid = 100
        self.started = 1_000

    def stop(self) -> None:
        if not self.running:
            raise HostError("double_stop")
        self.running = False

    def reload(self) -> None:
        if self.running:
            raise HostError("reload_while_running")

    def start(self) -> None:
        if self.running:
            raise HostError("double_start")
        self.running = True
        self.pid += 1
        self.started += 1

    def observe(self) -> dict[str, str]:
        return {
            "ActiveState": "active" if self.running else "inactive",
            "ExecMainStartTimestampMonotonic": str(self.started),
            "ExecStart": "",
            "MainPID": str(self.pid if self.running else 0),
            "NRestarts": "0",
            "SubState": "running" if self.running else "dead",
        }


@final
class SystemdService:
    """Exact user-systemd service manager."""

    def __init__(self, service: str) -> None:
        self._service = service

    @property
    def name(self) -> str:
        """Return the sealed service identity."""
        return self._service

    @property
    def running(self) -> bool:
        state = self.observe()
        return state["ActiveState"] == "active" and state["SubState"] == "running"

    def observe(self) -> dict[str, str]:
        fields = (
            "ActiveState",
            "SubState",
            "MainPID",
            "ExecStart",
            "ExecMainStartTimestampMonotonic",
            "NRestarts",
        )
        command = ["/usr/bin/systemctl", "--user", "show", self._service]
        command.extend(f"--property={field}" for field in fields)
        result = subprocess.run(command, check=True, capture_output=True, text=True)
        values = dict(
            line.split("=", 1) for line in result.stdout.splitlines() if "=" in line
        )
        return {field: values.get(field, "") for field in fields}

    def _run(self, *arguments: str) -> None:
        _ = subprocess.run(arguments, check=True, capture_output=True)

    def stop(self) -> None:
        self._run(
            "/usr/bin/systemctl",
            "--user",
            "stop",
            self._service,
        )

    def reload(self) -> None:
        self._run("/usr/bin/systemctl", "--user", "daemon-reload")

    def start(self) -> None:
        self._run(
            "/usr/bin/systemctl",
            "--user",
            "start",
            self._service,
        )


@dataclass(frozen=True, slots=True)
class HostPaths:
    """All target paths bound before authorization."""

    profile: Path
    registry: Path
    config: Path
    unit: Path
    dropin: Path
    current_runtime: Path
    successor_runtime: Path
    execution_root: Path
    ledger_root: Path
    protected_inventory: Path | None = None

    @property
    def mutable(self) -> tuple[Path, ...]:
        return self.config, self.registry, self.unit, self.dropin
