"""Glob tool - find files by name pattern."""

from __future__ import annotations

import os
from pathlib import Path

from krim.tools.base import Tool
from krim.truncate import truncate


class GlobTool(Tool):
    name = "glob"
    description = (
        "Find files by glob pattern (e.g. '**/*.py', 'src/**/*.ts'). "
        "Returns paths sorted by modification time (newest first). "
        "Use to discover project structure and locate files by name."
    )
    parameters = {
        "pattern": {
            "type": "string",
            "description": "Glob pattern (e.g. '**/*.py', 'src/**/*.ts', '*.json')",
        },
        "path": {
            "type": "string",
            "description": "Base directory to search from (default: current directory)",
            "optional": True,
        },
    }

    def __init__(self, max_output_chars: int = 30_000):
        self._max_output_chars = max_output_chars

    def run(self, pattern: str, path: str = ".") -> str:
        path = os.path.expanduser(path)
        base = Path(path)
        if not base.is_dir():
            return f"error: {path} is not a directory"

        try:
            matches = list(base.glob(pattern))
        except Exception as e:
            return f"error: invalid pattern: {e}"

        # filter out hidden dirs/files and common noise
        filtered = [
            m for m in matches
            if not any(part.startswith(".") for part in m.parts if part != ".")
            and "__pycache__" not in m.parts
            and "node_modules" not in m.parts
        ]

        if not filtered:
            return "no files matched"

        # sort by modification time, newest first
        filtered.sort(key=lambda p: p.stat().st_mtime if p.exists() else 0, reverse=True)

        # cap results
        max_results = 200
        lines = []
        for p in filtered[:max_results]:
            try:
                rel = p.relative_to(base)
            except ValueError:
                rel = p
            lines.append(str(rel))

        if len(filtered) > max_results:
            lines.append(f"... ({len(filtered) - max_results} more files)")

        return truncate("\n".join(lines), self._max_output_chars)
