import subprocess
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Any, Protocol

from ..config import CollectorConfig
from ..models import CollectorError, CollectorResult
from ..timeutil import utc_now


@dataclass(frozen=True, slots=True)
class CollectorContext:
    now: datetime
    host: str
    config: CollectorConfig
    base_dir: Path


class Collector(Protocol):
    name: str
    version: str

    def collect(self, context: CollectorContext) -> CollectorResult:
        ...


class CommandRunner(Protocol):
    def run(self, args: list[str], timeout_seconds: int) -> tuple[int, str, str]:
        ...


class SubprocessCommandRunner:
    def run(self, args: list[str], timeout_seconds: int) -> tuple[int, str, str]:
        completed = subprocess.run(args, capture_output=True, text=True, timeout=timeout_seconds, check=False)
        return completed.returncode, completed.stdout, completed.stderr


def result(name: str, version: str, started: datetime, observations: list[Any], errors: list[CollectorError], diagnostics: dict[str, Any] | None = None) -> CollectorResult:
    finished = utc_now()
    return CollectorResult(name, version, started, finished, not errors, tuple(observations), tuple(errors), diagnostics or {})
