"""Helpers for resolving CogniFlow workspace/semantics locations."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Optional
import os


SEMANTICS_DB_FILES = {
    "ontology": "cf-ontology.duckdb",
    "steps": "cf-steps.duckdb",
    "pipelines": "cf-pipelines.duckdb",
    "pipeline_states": "cf-pipeline-states.duckdb",
}


@dataclass(frozen=True)
class SemanticsDbPaths:
    """Container for the resolved DuckDB file paths used by semantics storage."""

    ontology: Path
    steps: Path
    pipelines: Path
    pipeline_states: Path

    def as_dict(self) -> dict[str, Path]:
        """Return the contained paths as a stable name-to-path mapping."""
        return {
            "ontology": self.ontology,
            "steps": self.steps,
            "pipelines": self.pipelines,
            "pipeline_states": self.pipeline_states,
        }


def find_repo_root(start: Optional[Path] = None) -> Optional[Path]:
    """
    Best-effort repository root discovery.

    We prefer a directory containing a `.git` folder. When the package is used from an
    installed environment (no repo checkout), this may return None.
    """
    probe = (start or Path.cwd()).resolve()
    for candidate in (probe, *probe.parents):
        if (candidate / ".git").exists():
            return candidate
        if (candidate / "sandcastle").is_dir() and (candidate / ".github").is_dir():
            return candidate
    return None


def resolve_workspace_dir() -> Path:
    """
    Resolve the workspace directory.

    Priority:
    1) `CF_WORKSPACE_DIR` (absolute or repo-relative)
    2) `<repo-root>/workspace`
    3) `<home>/.cogniflow/workspace`
    """
    repo_root = find_repo_root()
    raw = os.environ.get("CF_WORKSPACE_DIR")
    if raw:
        candidate = Path(raw).expanduser()
        if not candidate.is_absolute():
            candidate = (repo_root or Path.cwd()) / candidate
        return candidate.resolve()

    if repo_root:
        return (repo_root / "workspace").resolve()

    return (Path.home() / ".cogniflow" / "workspace").resolve()


def resolve_semantics_dir() -> Path:
    """
    Resolve the semantics directory.

    Priority:
    1) `CF_SEMANTICS_DIR` (absolute or repo-relative)
    2) `<workspace>/semantics`
    """
    repo_root = find_repo_root()
    raw = os.environ.get("CF_SEMANTICS_DIR")
    if raw:
        candidate = Path(raw).expanduser()
        if not candidate.is_absolute():
            candidate = (repo_root or Path.cwd()) / candidate
        return candidate.resolve()

    return (resolve_workspace_dir() / "semantics").resolve()


def resolve_semantics_db_path(
    semantics_dir: Optional[Path] = None,
    kind: str = "ontology",
) -> Path:
    """Return the DuckDB file path for a specific semantics database."""
    base = semantics_dir or resolve_semantics_dir()
    normalized = kind.strip().lower().replace("-", "_")
    filename = SEMANTICS_DB_FILES.get(normalized)
    if not filename:
        raise ValueError(f"Unknown semantics db kind: {kind}")
    return base / filename


def resolve_semantics_db_paths(
    semantics_dir: Optional[Path] = None,
) -> SemanticsDbPaths:
    """Return all semantics DB paths for the given semantics directory."""
    base = semantics_dir or resolve_semantics_dir()
    return SemanticsDbPaths(
        ontology=base / SEMANTICS_DB_FILES["ontology"],
        steps=base / SEMANTICS_DB_FILES["steps"],
        pipelines=base / SEMANTICS_DB_FILES["pipelines"],
        pipeline_states=base / SEMANTICS_DB_FILES["pipeline_states"],
    )
