"""
Project registry management for Lattice.

Manages projects.toml registration and project lifecycle.

Reference: RFC-002 §6.1
"""

# @invar:allow shell_result: Path getters, no I/O needed
# @invar:allow shell_pure_logic: Path computation helpers
from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path

from returns.result import Failure, Result, Success

from lattice.core.types.evidence import ProjectRegistration
from lattice.shell.config import resolve_global_dir


# @invar:allow shell_result: Path getter, no I/O
# @invar:allow shell_pure_logic: Pure path computation
def get_projects_path() -> Path:
    """Get path to projects.toml (in ~/.config/lattice/).

    Returns:
        Path to projects.toml.
    """
    result = resolve_global_dir()
    if isinstance(result, Success):
        return result.unwrap() / "projects.toml"
    return Path.home() / ".config" / "lattice" / "projects.toml"


# @invar:allow shell_result: Path getter, no I/O
# @invar:allow shell_pure_logic: Pure path computation
def get_projects_dir() -> Path:
    """Get path to ~/.config/lattice/ directory.

    Returns:
        Path to global lattice directory.
    """
    result = resolve_global_dir()
    if isinstance(result, Success):
        return result.unwrap()
    return Path.home() / ".config" / "lattice"


@dataclass(frozen=True)
class ProjectInfo:
    """Project info with status."""

    name: str
    path: str
    registered_at: str
    exists: bool


def load_projects() -> Result[list[ProjectRegistration], str]:
    """Load all registered projects from projects.toml.

    Returns:
        Success(list of ProjectRegistration) or Failure(error).
    """
    import tomllib

    projects_path = get_projects_path()
    if not projects_path.exists():
        return Success([])

    try:
        with open(projects_path, "rb") as f:
            data = tomllib.load(f)

        projects = []
        for name, info in data.get("projects", {}).items():
            projects.append(
                ProjectRegistration(
                    path=info.get("path", ""),
                    name=name,
                    registered_at=info.get("registered_at", ""),
                )
            )
        return Success(projects)
    except Exception as e:
        return Failure(f"Failed to load projects: {e}")


def save_projects(projects: list[ProjectRegistration]) -> Result[None, str]:
    """Save projects to projects.toml.

    Returns:
        Success(None) or Failure(error).
    """
    projects_path = get_projects_path()
    projects_path.parent.mkdir(parents=True, exist_ok=True)

    try:
        lines = ["# Lattice Project Registry\n", "\n", "[projects]\n"]
        for proj in projects:
            lines.append(f'\n[projects."{proj.name}"]\n')
            lines.append(f'path = "{proj.path}"\n')
            lines.append(f'registered_at = "{proj.registered_at}"\n')

        projects_path.write_text("".join(lines), encoding="utf-8")
        return Success(None)
    except Exception as e:
        return Failure(f"Failed to save projects: {e}")


def register_project(
    path: str, name: str | None = None
) -> Result[ProjectRegistration, str]:
    """Register a project in projects.toml.

    Args:
        path: Path to project directory.
        name: Optional project name (default: directory name).

    Returns:
        Success(ProjectRegistration) or Failure(error).
    """
    proj_path = Path(path).resolve()
    if not proj_path.exists():
        return Failure(f"Path does not exist: {proj_path}")

    if not proj_path.is_dir():
        return Failure(f"Path is not a directory: {proj_path}")

    project_name = name or proj_path.name
    timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")

    registration = ProjectRegistration(
        path=str(proj_path),
        name=project_name,
        registered_at=timestamp,
    )

    # Load existing projects
    load_result = load_projects()
    if isinstance(load_result, Failure):
        projects = []
    else:
        projects = load_result.unwrap()

    # Check for duplicate
    for p in projects:
        if p.name == project_name:
            return Failure(f"Project '{project_name}' already registered")
        if p.path == str(proj_path):
            return Failure(f"Path already registered as '{p.name}'")

    # Add new project
    projects.append(registration)

    # Save
    save_result = save_projects(projects)
    if isinstance(save_result, Failure):
        return save_result

    return Success(registration)


def unregister_project(name: str) -> Result[None, str]:
    """Remove a project from the registry.

    Args:
        name: Project name to remove.

    Returns:
        Success(None) or Failure(error).
    """
    load_result = load_projects()
    if isinstance(load_result, Failure):
        return load_result

    projects = load_result.unwrap()
    original_count = len(projects)
    projects = [p for p in projects if p.name != name]

    if len(projects) == original_count:
        return Failure(f"Project '{name}' not found")

    return save_projects(projects)


def list_projects() -> Result[list[ProjectInfo], str]:
    """List all registered projects with status.

    Returns:
        Success(list of ProjectInfo) or Failure(error).
    """
    load_result = load_projects()
    if isinstance(load_result, Failure):
        return load_result

    projects = load_result.unwrap()
    infos = []

    for proj in projects:
        path = Path(proj.path)
        infos.append(
            ProjectInfo(
                name=proj.name,
                path=proj.path,
                registered_at=proj.registered_at,
                exists=path.exists(),
            )
        )

    return Success(infos)


def verify_projects() -> Result[list[tuple[str, bool, str]], str]:
    """Verify all registered project paths exist.

    Returns:
        Success(list of (name, exists, message)) or Failure(error).
    """
    load_result = load_projects()
    if isinstance(load_result, Failure):
        return load_result

    projects = load_result.unwrap()
    results = []

    for proj in projects:
        path = Path(proj.path)
        if path.exists():
            if (path / ".lattice").exists():
                results.append((proj.name, True, "OK"))
            else:
                results.append((proj.name, False, "Missing .lattice/"))
        else:
            results.append((proj.name, False, "Path not found"))

    return Success(results)


__all__ = [
    "get_projects_path",
    "get_projects_dir",
    "load_projects",
    "save_projects",
    "register_project",
    "unregister_project",
    "list_projects",
    "verify_projects",
    "ProjectInfo",
]
