# standard
from pathlib import Path
from typing import Optional

# custom
from sunwaee.modules.tasks.model import Task
from sunwaee.config import (
    get_all_workspaces,
    get_default_workspace,
    get_module_dir,
)
from sunwaee.core.fs import find_md, list_md, make_slug, read_md, write_md


def _resolve_dir(workspace: Optional[str]) -> tuple[str, Path]:
    workspace = workspace or get_default_workspace()
    return workspace, get_module_dir(workspace, "tasks")


def _resolve_dirs(workspace: Optional[str]) -> list[tuple[str, Path]]:
    if workspace:
        return [_resolve_dir(workspace)]
    return [_resolve_dir(ws) for ws in get_all_workspaces()]


def _find_in_all(
    query: str, workspace: Optional[str]
) -> Optional[tuple[str, Path, Path]]:
    """Search for a task across workspaces. Returns (ws_name, directory, path) or None."""
    for ws, directory in _resolve_dirs(workspace):
        path = find_md(query, directory)
        if path is not None:
            return ws, directory, path
    return None


def _load(path: Path) -> Task:
    meta, body = read_md(path)
    return Task.from_dict(meta, body)


def _save(task: Task, directory: Path, path: Optional[Path] = None) -> Path:
    if path is None:
        slug = make_slug(task.title, task.id)
        path = directory / f"{slug}.md"
    write_md(path, task.to_frontmatter_meta(), task.body)
    return path


def _enrich(task: Task, workspace: str, path: Path) -> dict:
    d = task.to_dict()
    d["workspace"] = workspace
    d["path"] = str(path)
    return d


def _find_children(parent_id: str, directory: Path) -> list[tuple[Task, Path]]:
    results = []
    for p in list_md(directory):
        task = _load(p)
        if task.parent_id == parent_id:
            results.append((task, p))
    return results


def _delete_cascade(task: Task, path: Path, directory: Path) -> list[tuple[Task, Path]]:
    deleted = []
    for child, child_path in _find_children(task.id, directory):
        deleted.extend(_delete_cascade(child, child_path, directory))
    path.unlink()
    deleted.append((task, path))
    return deleted
