# standard
from typing import Annotated, Literal

# third party
# custom
from sunwaee.config import (
    get_active_project,
    get_all_projects,
    get_default_workspace,
    get_project_dir,
    get_workspace_dir,
    set_default_project,
)
from sunwaee.core.audit import append_log
from sunwaee.core.fs import read_md, write_md
from sunwaee.core.git import ensure_git_repo
from sunwaee.core.tools import err, ok, tool
from sunwaee.modules.projects.model import Project


def _load(ws: str, name: str) -> Project | None:
    meta_path = get_project_dir(ws, name) / "metadata.md"
    if not meta_path.exists():
        return None
    meta, body = read_md(meta_path)
    return Project.from_dict(name, meta, body)


@tool(
    "Manage projects. Actions: "
    "'create' (requires name, optional workspace and body), "
    "'list' returns all projects in the given workspace with full metadata, "
    "'read' (requires name, optional workspace) returns a single project in full detail, "
    "'update' (requires name; optional workspace, body, set_default)."
)
def projects(
    action: Annotated[Literal["create", "list", "read", "update"], "Action to perform"],
    name: Annotated[str | None, "Project name — required for create/update"] = None,
    workspace: Annotated[str | None, "Workspace name (uses default if omitted)"] = None,
    body: Annotated[str | None, "Project description / details (markdown)"] = None,
    set_default: Annotated[bool, "Set as the default project (update only)"] = False,
) -> str:
    ws = workspace or get_default_workspace()

    if action == "list":
        default = get_active_project(ws)
        result = []
        for project_name in get_all_projects(ws):
            proj = _load(ws, project_name) or Project(name=project_name)
            entry = proj.to_dict()
            entry["workspace"] = ws
            entry["default"] = proj.name == default
            result.append(entry)
        return ok(result)

    if not name:
        return err(f"'name' is required for action={action!r}")

    if action == "create":
        project_dir = get_project_dir(ws, name)
        if project_dir.exists():
            return err(f"Project already exists: {name!r}")
        project_dir.mkdir(parents=True, exist_ok=True)
        ensure_git_repo(get_workspace_dir(ws))
        proj = Project(name=name, body=body or "")
        write_md(project_dir / "metadata.md", proj.to_frontmatter_meta(), proj.body)
        append_log(ws, "projects", "create", item_id=proj.id, item_title=name)
        data = proj.to_dict()
        data["workspace"] = ws
        data["path"] = str(project_dir)
        return ok(data)

    if action == "read":
        project_dir = get_project_dir(ws, name)
        if not project_dir.exists():
            return err(f"Project not found: {name!r}")
        proj = _load(ws, name) or Project(name=name)
        append_log(ws, "projects", "read", item_id=proj.id, item_title=name)
        data = proj.to_dict()
        data["workspace"] = ws
        data["default"] = get_active_project(ws) == name
        return ok(data)

    if action == "update":
        project_dir = get_project_dir(ws, name)
        if not project_dir.exists():
            return err(f"Project not found: {name!r}")
        if body is None and not set_default:
            return err("Specify at least one of body or set_default=true")
        proj = _load(ws, name) or Project(name=name)
        if body is not None:
            proj.body = body
        if set_default:
            set_default_project(ws, name)
        proj.touch()
        write_md(project_dir / "metadata.md", proj.to_frontmatter_meta(), proj.body)
        append_log(ws, "projects", "update", item_id=proj.id, item_title=name)
        data = proj.to_dict()
        data["workspace"] = ws
        data["default"] = get_active_project(ws) == name
        return ok(data)

    return err(f"Unknown action: {action!r}")  # pragma: no cover


TOOLS = [projects._tool]
