"""
Global projects registry for TurboSEO.

Tracks all TurboSEO-configured projects across the system.
"""

import tomllib
from datetime import datetime
from pathlib import Path

from pydantic import BaseModel, Field

from turboseo.config.loader import get_global_dir

PROJECTS_FILE = "projects.toml"


class ProjectInfo(BaseModel):
    """Information about a registered project."""

    name: str = Field(description="Project name")
    path: str = Field(description="Absolute path to project")
    url: str = Field(default="", description="Project website URL")
    description: str = Field(default="", description="Short description")
    added: str = Field(description="ISO timestamp when added")
    last_used: str = Field(default="", description="ISO timestamp of last use")


def _get_projects_file() -> Path:
    """Get path to global projects file."""
    global_dir = get_global_dir()
    global_dir.mkdir(parents=True, exist_ok=True)
    return global_dir / PROJECTS_FILE


def list_projects() -> list[ProjectInfo]:
    """List all registered projects."""
    projects_file = _get_projects_file()

    if not projects_file.exists():
        return []

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

    projects = []
    for project_data in data.get("projects", []):
        try:
            projects.append(ProjectInfo(**project_data))
        except Exception:
            continue  # Skip invalid entries

    return projects


def get_project(name_or_path: str) -> ProjectInfo | None:
    """
    Get a project by name or path.

    Args:
        name_or_path: Project name or absolute path.

    Returns:
        ProjectInfo if found, None otherwise.
    """
    projects = list_projects()

    # First try exact name match
    for p in projects:
        if p.name.lower() == name_or_path.lower():
            return p

    # Then try path match
    for p in projects:
        if p.path == name_or_path or p.path == str(Path(name_or_path).resolve()):
            return p

    return None


def add_project(
    name: str,
    path: Path,
    url: str = "",
    description: str = "",
) -> ProjectInfo:
    """
    Add or update a project in the registry.

    Args:
        name: Project name.
        path: Absolute path to project.
        url: Optional project URL.
        description: Optional description.

    Returns:
        The created/updated ProjectInfo.
    """
    projects = list_projects()

    # Check if already exists (by path)
    path_str = str(path.resolve())
    existing_idx = None
    for i, p in enumerate(projects):
        if p.path == path_str:
            existing_idx = i
            break

    now = datetime.now().isoformat()

    if existing_idx is not None:
        # Update existing
        project = projects[existing_idx]
        project.name = name
        project.url = url or project.url
        project.description = description or project.description
        project.last_used = now
    else:
        # Create new
        project = ProjectInfo(
            name=name,
            path=path_str,
            url=url,
            description=description,
            added=now,
            last_used=now,
        )
        projects.append(project)

    _save_projects(projects)
    return project


def remove_project(name_or_path: str) -> bool:
    """
    Remove a project from the registry.

    Args:
        name_or_path: Project name or path.

    Returns:
        True if removed, False if not found.
    """
    projects = list_projects()

    # Find index to remove
    remove_idx = None
    for i, p in enumerate(projects):
        if p.name.lower() == name_or_path.lower() or p.path == name_or_path:
            remove_idx = i
            break

    if remove_idx is None:
        return False

    projects.pop(remove_idx)
    _save_projects(projects)
    return True


def update_last_used(name_or_path: str) -> None:
    """Update the last_used timestamp for a project."""
    projects = list_projects()

    for p in projects:
        if p.name.lower() == name_or_path.lower() or p.path == name_or_path:
            p.last_used = datetime.now().isoformat()
            _save_projects(projects)
            return


def _save_projects(projects: list[ProjectInfo]) -> None:
    """Save projects to the global registry file."""
    projects_file = _get_projects_file()

    lines = ["# TurboSEO Projects Registry", "# Auto-generated - do not edit manually", ""]

    for project in projects:
        lines.append("[[projects]]")
        lines.append(f'name = "{project.name}"')
        lines.append(f'path = "{project.path}"')
        if project.url:
            lines.append(f'url = "{project.url}"')
        if project.description:
            escaped = project.description.replace('"', '\\"')
            lines.append(f'description = "{escaped}"')
        lines.append(f'added = "{project.added}"')
        if project.last_used:
            lines.append(f'last_used = "{project.last_used}"')
        lines.append("")

    projects_file.write_text("\n".join(lines))
