#!/usr/bin/env python3
# ollie:parallel read
# args_json: {"type":"object","required":["pattern"],"properties":{"pattern":{"type":"string","description":"Regex pattern to search"},"path":{"type":"string","description":"Search directory (default: cwd)"},"mode":{"type":"string","description":"content|files_with_matches|count (default: content)"},"glob":{"type":"string","description":"File glob filter"},"type":{"type":"string","description":"File type filter (rg --type)"},"case_insensitive":{"type":"boolean","description":"Case-insensitive search"},"after":{"type":"integer","description":"Lines after match (-A)"},"before":{"type":"integer","description":"Lines before match (-B)"},"context":{"type":"integer","description":"Lines around match (-C)"},"multiline":{"type":"boolean","description":"Enable multiline matching"},"head":{"type":"integer","description":"Max results to return (default: 50)"},"offset":{"type":"integer","description":"Skip first N results"}}}
# ollie:prompt
# ## file_grep
#
# Search file contents with ripgrep. Capped at 50 matches by default.
#
# **Args**: `pattern` (required), plus optional named params.
#
# ```
# file_grep(pattern="pattern", path="/abs/dir")
# file_grep(pattern="TODO", path="src/", glob="*.go", case_insensitive=true)
# file_grep(pattern="func main", path="/home/user/project")
# ```
#
# - `path`: search directory (not a positional arg)
# - `glob`: file glob filter
# - `case_insensitive`: boolean
#
# **Params**: `path`, `mode` (content|files_with_matches|count), `glob`, `type`, `case_insensitive`, `before`, `after`, `context`, `multiline`, `head`, `offset`.
# ollie:end

import sys
import os
import subprocess
import shutil

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from _lib.args import parse_args

args = parse_args()
pattern = args.require("pattern")
search_path = args.get("path", os.getcwd())
mode = args.get("mode", "content")
glob_pat = args.get("glob")
type_filter = args.get("type")
case_insensitive = args.get_bool("case_insensitive")
after = args.get_int("after")
before = args.get_int("before")
context_lines = args.get_int("context")
multiline = args.get_bool("multiline")
head = args.get_int("head", 0)
offset = args.get_int("offset", 0)

use_rg = shutil.which('rg') is not None

if use_rg:
    cmd = ['rg', '--no-config', '--color=never']

    if mode == 'files_with_matches':
        cmd.append('-l')
    elif mode == 'count':
        cmd.append('--count')
    else:
        cmd.append('-n')

    if case_insensitive:
        cmd.append('-i')
    if multiline:
        cmd += ['-U', '--multiline-dotall']
    if glob_pat:
        cmd += ['-g', glob_pat]
    if type_filter:
        cmd += ['-t', type_filter]
    if context_lines is not None:
        cmd += ['-C', str(context_lines)]
    if after is not None:
        cmd += ['-A', str(after)]
    if before is not None:
        cmd += ['-B', str(before)]

    cmd += ['-e', pattern, search_path]
else:
    cmd = ['grep', '-r', '--color=never']

    if mode == 'files_with_matches':
        cmd.append('-l')
    elif mode == 'count':
        cmd.append('-c')
    else:
        cmd.append('-n')

    if case_insensitive:
        cmd.append('-i')
    if glob_pat:
        cmd += ['--include=' + glob_pat]
    if context_lines is not None:
        cmd += ['-C', str(context_lines)]
    if after is not None:
        cmd += ['-A', str(after)]
    if before is not None:
        cmd += ['-B', str(before)]

    cmd += ['-e', pattern, search_path]

result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 1:
    print("STATUS=no_matches MATCH_COUNT=0")
    print("no matches")
    sys.exit(0)
if result.returncode > 1:
    print(f"STATUS=error")
    print(f"error: {result.stderr.strip() or f'search exited with {result.returncode}'}")
    sys.exit(1)

lines = result.stdout.splitlines()
total = len(lines)

if offset:
    lines = lines[offset:]

max_matches = head if head else 50
capped = len(lines) > max_matches
if capped:
    lines = lines[:max_matches]

if mode == 'content':
    formatted = []
    for line in lines:
        if line == '--':
            formatted.append(line)
            continue
        for sep in (':', '-'):
            parts = line.split(sep, 2)
            if len(parts) == 3 and parts[1].isdigit():
                formatted.append(f"{parts[0]}:{parts[1]:>5}| {parts[2]}")
                break
        else:
            formatted.append(line)
    lines = formatted

print(f"STATUS=ok MATCH_COUNT={total}")
print('\n'.join(lines))
if capped:
    print(f"\n(showing {max_matches} of {total} matches; use --head=N or --offset=N for more)")
