"""Discover session folders and read pipeline state from disk."""

from __future__ import annotations

import json
from dataclasses import dataclass, field
from pathlib import Path

from mixersystem.studio.log_parser import TraceSummary, parse_trace_log
from mixersystem.studio.trace_db import has_trace_db, query_summary

WORKFLOW_STAGES = ["task", "plan", "work", "update", "upgrade", "report"]
ALL_WORKFLOWS = WORKFLOW_STAGES + ["questions"]


_SESSION_SKIP_NAMES = {"logs", "branches"}


@dataclass
class SessionFolderInfo:
    path: Path
    name: str
    artifacts: dict[str, bool] = field(default_factory=dict)
    has_questions: dict[str, bool] = field(default_factory=dict)
    current_stage: str = ""
    trace_summary: TraceSummary | None = None
    last_activity: float = 0.0  # epoch seconds from folder mtime
    children: list["SessionFolderInfo"] = field(default_factory=list)


def _has_questions(path: Path) -> bool:
    """Return True only if the file exists AND contains at least one question."""
    if not path.is_file():
        return False
    try:
        data = json.loads(path.read_text())
        return bool(data.get("questions"))
    except (json.JSONDecodeError, OSError):
        return False


def scan_session_folder(folder: Path) -> SessionFolderInfo:
    """Read one session folder's state from disk."""
    artifacts = {}
    has_questions = {}
    current_stage = ""
    for stage in WORKFLOW_STAGES:
        exists = (folder / f"{stage}.md").is_file()
        artifacts[stage] = exists
        has_questions[stage] = _has_questions(folder / f"{stage}_questions.json")
        if exists:
            current_stage = stage

    trace_summary = None
    if has_trace_db(folder):
        db_summary = query_summary(folder)
        trace_summary = TraceSummary(
            total_calls=db_summary.total_calls,
            total_duration_seconds=db_summary.total_duration_seconds,
            total_cost_usd=db_summary.total_cost_usd,
            agents=db_summary.agents,
        )
    else:
        trace_log = folder / "logs" / "agent_trace.log"
        if trace_log.is_file():
            trace_summary = parse_trace_log(trace_log)

    last_activity = folder.stat().st_mtime

    return SessionFolderInfo(
        path=folder,
        name=folder.name,
        artifacts=artifacts,
        has_questions=has_questions,
        current_stage=current_stage,
        trace_summary=trace_summary,
        last_activity=last_activity,
    )


def discover_session_folders(sessions_dir: Path) -> list[SessionFolderInfo]:
    """Scan .mixer/sessions/ for folders containing at least one artifact .md."""
    if not sessions_dir.is_dir():
        return []

    results = []
    for child in sessions_dir.iterdir():
        if not child.is_dir() or child.name.startswith(('.', '_')):
            continue
        results.append(scan_session_folder(child))
    results.sort(key=lambda f: f.last_activity, reverse=True)
    return results


def _is_session_child(path: Path) -> bool:
    """Return True if path is a subfolder that should be treated as a child session."""
    if not path.is_dir():
        return False
    name = path.name
    if name in _SESSION_SKIP_NAMES:
        return False
    if name.startswith('.') or name.startswith('_'):
        return False
    return True


def _scan_tree(folder: Path, sessions_dir: Path) -> SessionFolderInfo:
    """Recursively scan a session folder and its children."""
    # Compute relative name from sessions_dir (e.g., "parent/child")
    rel_name = str(folder.relative_to(sessions_dir))
    info = scan_session_folder(folder)
    info.name = rel_name

    children = []
    for child in sorted(folder.iterdir()):
        if _is_session_child(child):
            children.append(_scan_tree(child, sessions_dir))
    children.sort(key=lambda f: f.last_activity, reverse=True)
    info.children = children
    return info


def discover_session_tree(sessions_dir: Path) -> list[SessionFolderInfo]:
    """Scan .mixer/sessions/ recursively, returning a tree of session folders."""
    if not sessions_dir.is_dir():
        return []

    results = []
    for child in sessions_dir.iterdir():
        if not child.is_dir() or child.name.startswith(('.', '_')):
            continue
        results.append(_scan_tree(child, sessions_dir))
    results.sort(key=lambda f: f.last_activity, reverse=True)
    return results
