# SCCS Hub README Generator
# Generates a navigation README for the sync repository

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from pathlib import Path

from sccs import __version__
from sccs.config.schema import SccsConfig
from sccs.utils.paths import atomic_write, expand_path

MARKER = "<!-- AUTO-GENERATED BY SCCS - DO NOT EDIT MANUALLY -->"


@dataclass
class ReadmeInfo:
    """Information about a discovered README file."""

    category_name: str
    description: str
    repo_relative_path: str  # e.g. ".claude/skills/README.md"
    title: str  # First # heading
    enabled: bool


@dataclass
class CategoryInfo:
    """Metadata for a sync category."""

    name: str
    description: str
    enabled: bool
    sync_mode: str
    item_type: str
    item_count: int
    has_readme: bool
    readme_path: str | None


@dataclass
class DocsResult:
    """Result of hub README generation."""

    success: bool
    readme_path: Path | None = None
    readmes_found: int = 0
    categories_total: int = 0
    error: str | None = None


class DocsGenerator:
    """Generates a hub README for the sync repository."""

    def __init__(self, config: SccsConfig) -> None:
        self._config = config
        self._repo_path = expand_path(config.repository.path)

    def generate(self, *, dry_run: bool = False) -> DocsResult:
        """Generate the hub README.

        Args:
            dry_run: If True, render but don't write.

        Returns:
            DocsResult with generation outcome.
        """
        try:
            content = self.render_readme()
            readme_path = self._repo_path / "README.md"

            readmes = self._discover_readmes()
            categories = self._collect_categories()

            if not dry_run:
                atomic_write(readme_path, content)

            return DocsResult(
                success=True,
                readme_path=readme_path,
                readmes_found=len(readmes),
                categories_total=len(categories),
            )
        except Exception as e:
            return DocsResult(success=False, error=str(e))

    def render_readme(self) -> str:
        """Render the complete hub README markdown content."""
        readmes = self._discover_readmes()
        categories = self._collect_categories()
        tree = self._build_directory_tree()
        now = datetime.now().strftime("%Y-%m-%d %H:%M")

        lines: list[str] = []

        # Header with marker
        lines.append(MARKER)
        lines.append("# SCCS Sync Repository")
        lines.append("")
        lines.append(f"> Auto-generated documentation hub | Updated: {now}")
        lines.append(f"> Generated by SCCS v{__version__}")
        lines.append("")

        # Documentation section
        lines.append("## Documentation")
        lines.append("")
        if readmes:
            lines.append("| Document | Area | Description |")
            lines.append("|----------|------|-------------|")
            for info in readmes:
                link = f"[{info.title}]({info.repo_relative_path})"
                lines.append(f"| {link} | {info.category_name} | {info.description} |")
        else:
            lines.append("*No README files found in sync categories.*")
        lines.append("")

        # Categories section
        lines.append("## Sync Categories")
        lines.append("")
        lines.append("| Category | Status | Mode | Items | Description |")
        lines.append("|----------|--------|------|-------|-------------|")
        for cat in categories:
            status = "\u2705" if cat.enabled else "\u26d4"
            lines.append(f"| {cat.name} | {status} | {cat.sync_mode} | {cat.item_count} | {cat.description} |")
        lines.append("")

        # Repository structure
        lines.append("## Repository Structure")
        lines.append("")
        lines.append("```")
        lines.append(tree)
        lines.append("```")
        lines.append("")

        # Footer
        lines.append("---")
        lines.append("*Auto-generated by `sccs docs generate`. Do not edit manually.*")
        lines.append("")

        return "\n".join(lines)

    def _discover_readmes(self) -> list[ReadmeInfo]:
        """Scan repo for README.md files in category paths."""
        readmes: list[ReadmeInfo] = []

        for name, cat in self._config.sync_categories.items():
            repo_dir = self._repo_path / cat.repo_path
            readme_path = repo_dir / "README.md"

            if readme_path.is_file():
                title = self._extract_title(readme_path)
                rel_path = str(readme_path.relative_to(self._repo_path))
                readmes.append(
                    ReadmeInfo(
                        category_name=name,
                        description=cat.description,
                        repo_relative_path=rel_path,
                        title=title,
                        enabled=cat.enabled,
                    )
                )

        return readmes

    def _collect_categories(self) -> list[CategoryInfo]:
        """Collect metadata for all sync categories."""
        categories: list[CategoryInfo] = []

        for name, cat in self._config.sync_categories.items():
            repo_dir = self._repo_path / cat.repo_path
            readme_path = repo_dir / "README.md"
            has_readme = readme_path.is_file()

            # Count items in repo path
            item_count = 0
            if repo_dir.is_dir():
                if cat.item_type.value == "directory":
                    item_count = sum(1 for p in repo_dir.iterdir() if p.is_dir())
                elif cat.item_type.value == "file":
                    item_count = sum(1 for p in repo_dir.iterdir() if p.is_file())
                else:  # mixed
                    item_count = sum(1 for p in repo_dir.iterdir() if not p.name.startswith("."))

            categories.append(
                CategoryInfo(
                    name=name,
                    description=cat.description,
                    enabled=cat.enabled,
                    sync_mode=cat.sync_mode.value,
                    item_type=cat.item_type.value,
                    item_count=item_count,
                    has_readme=has_readme,
                    readme_path=str(readme_path.relative_to(self._repo_path)) if has_readme else None,
                )
            )

        return categories

    def _build_directory_tree(self, max_depth: int = 3) -> str:
        """Build an ASCII directory tree of the repo."""
        if not self._repo_path.is_dir():
            return f"{self._repo_path.name}/ (not found)"

        lines: list[str] = [f"{self._repo_path.name}/"]
        self._walk_tree(self._repo_path, lines, prefix="", depth=0, max_depth=max_depth)
        return "\n".join(lines)

    def _walk_tree(
        self,
        directory: Path,
        lines: list[str],
        prefix: str,
        depth: int,
        max_depth: int,
    ) -> None:
        """Recursively walk directory tree and build ASCII representation."""
        if depth >= max_depth:
            return

        entries = sorted(
            [e for e in directory.iterdir() if not e.name.startswith(".")],
            key=lambda p: (not p.is_dir(), p.name.lower()),
        )

        # Collapse large directories (30+ items)
        if len(entries) > 30:
            dirs = [e for e in entries if e.is_dir()]
            files = [e for e in entries if e.is_file()]
            # Show first 5 dirs and a summary
            show_dirs = dirs[:5]
            show_files = files[:3]
            remaining = len(entries) - len(show_dirs) - len(show_files)
            entries = show_dirs + show_files
            collapse_note = f"... and {remaining} more items"
        else:
            collapse_note = None

        for i, entry in enumerate(entries):
            is_last = i == len(entries) - 1 and collapse_note is None
            connector = "\u2514\u2500\u2500 " if is_last else "\u251c\u2500\u2500 "
            child_prefix = "    " if is_last else "\u2502   "

            if entry.is_dir():
                lines.append(f"{prefix}{connector}{entry.name}/")
                self._walk_tree(entry, lines, prefix + child_prefix, depth + 1, max_depth)
            else:
                lines.append(f"{prefix}{connector}{entry.name}")

        if collapse_note:
            lines.append(f"{prefix}\u2514\u2500\u2500 {collapse_note}")

    @staticmethod
    def _extract_title(readme_path: Path) -> str:
        """Extract the first # heading from a README file."""
        try:
            with open(readme_path, encoding="utf-8") as f:
                for line in f:
                    line = line.strip()
                    if line.startswith("# "):
                        return line[2:].strip()
            return readme_path.parent.name
        except OSError:
            return readme_path.parent.name
