#!/usr/bin/env bash

set -euo pipefail

BASE_SHA="${BASE_SHA:-}"
DOCS_FILES_RAW="${DOCS_FILES:-}"

if [ -z "$BASE_SHA" ] && git rev-parse --verify origin/master >/dev/null 2>&1; then
    BASE_SHA="$(git merge-base origin/master HEAD)"
fi

if [ -z "$DOCS_FILES_RAW" ] && [ -n "$BASE_SHA" ] && git cat-file -e "$BASE_SHA^{commit}" 2>/dev/null; then
    DOCS_FILES_RAW="$(git diff --name-only "$BASE_SHA" HEAD | awk '
        /\.md$/ || /\.mdx$/ || $0 == "LICENSE" || $0 == ".github/pull_request_template.md" {
            print
        }
    ')"
fi

if [ -z "$DOCS_FILES_RAW" ]; then
    echo "No docs files detected; skipping docs quality gate."
    exit 0
fi

if [ -z "$BASE_SHA" ] || ! git cat-file -e "$BASE_SHA^{commit}" 2>/dev/null; then
    echo "BASE_SHA is missing or invalid; falling back to full-file markdown lint."
    BASE_SHA=""
fi

ALL_FILES=()
while IFS= read -r file; do
    if [ -n "$file" ]; then
        ALL_FILES+=("$file")
    fi
done < <(printf '%s\n' "$DOCS_FILES_RAW")

if [ "${#ALL_FILES[@]}" -eq 0 ]; then
    echo "No docs files detected after normalization; skipping docs quality gate."
    exit 0
fi

EXISTING_FILES=()
for file in "${ALL_FILES[@]}"; do
    if [ -f "$file" ]; then
        EXISTING_FILES+=("$file")
    fi
done

if [ "${#EXISTING_FILES[@]}" -eq 0 ]; then
    echo "No existing docs files to lint; skipping docs quality gate."
    exit 0
fi

if command -v npx >/dev/null 2>&1; then
    MD_CMD=(npx --yes markdownlint-cli2@0.20.0)
elif command -v markdownlint-cli2 >/dev/null 2>&1; then
    MD_CMD=(markdownlint-cli2)
else
    echo "markdownlint-cli2 is required (via npx or local binary)."
    exit 1
fi

echo "Linting docs files: ${EXISTING_FILES[*]}"

LINT_OUTPUT_FILE="$(mktemp)"
set +e
"${MD_CMD[@]}" "${EXISTING_FILES[@]}" >"$LINT_OUTPUT_FILE" 2>&1
LINT_EXIT=$?
set -e

if [ "$LINT_EXIT" -eq 0 ]; then
    cat "$LINT_OUTPUT_FILE"
    rm -f "$LINT_OUTPUT_FILE"
    exit 0
fi

if [ -z "$BASE_SHA" ]; then
    cat "$LINT_OUTPUT_FILE"
    rm -f "$LINT_OUTPUT_FILE"
    exit "$LINT_EXIT"
fi

CHANGED_LINES_JSON_FILE="$(mktemp)"
python3 - "$BASE_SHA" "${EXISTING_FILES[@]}" >"$CHANGED_LINES_JSON_FILE" <<'PY'
import json
import re
import subprocess
import sys

base = sys.argv[1]
files = sys.argv[2:]

changed = {}
hunk = re.compile(r"^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@")

for path in files:
    proc = subprocess.run(
        ["git", "diff", "--unified=0", base, "HEAD", "--", path],
        check=False,
        capture_output=True,
        text=True,
    )
    ranges = []
    for line in proc.stdout.splitlines():
        m = hunk.match(line)
        if not m:
            continue
        start = int(m.group(1))
        count = int(m.group(2) or "1")
        if count > 0:
            ranges.append([start, start + count - 1])
    changed[path] = ranges

print(json.dumps(changed))
PY

FILTERED_OUTPUT_FILE="$(mktemp)"
set +e
python3 - "$LINT_OUTPUT_FILE" "$CHANGED_LINES_JSON_FILE" >"$FILTERED_OUTPUT_FILE" <<'PY'
import json
import re
import sys

lint_file = sys.argv[1]
changed_file = sys.argv[2]

with open(changed_file, "r", encoding="utf-8") as f:
    changed = json.load(f)

line_re = re.compile(r"^(.+?):(\d+)\s+error\s+(MD\d+(?:/[^\s]+)?)\s+(.*)$")

blocking = []
baseline = []
other_lines = []

with open(lint_file, "r", encoding="utf-8") as f:
    for raw_line in f:
        line = raw_line.rstrip("\n")
        m = line_re.match(line)
        if not m:
            other_lines.append(line)
            continue

        path, line_no_s, rule, msg = m.groups()
        line_no = int(line_no_s)
        ranges = changed.get(path, [])

        is_changed_line = any(start <= line_no <= end for start, end in ranges)
        entry = f"{path}:{line_no} {rule} {msg}"
        if is_changed_line:
            blocking.append(entry)
        else:
            baseline.append(entry)

if baseline:
    print("Existing markdown issues outside changed lines (non-blocking):")
    for entry in baseline:
        print(f"  - {entry}")

if blocking:
    print("Markdown issues introduced on changed lines (blocking):")
    for entry in blocking:
        print(f"  - {entry}")
    print(f"Blocking markdown issues: {len(blocking)}")
    sys.exit(1)

if baseline:
    print("No blocking markdown issues on changed lines.")
    sys.exit(0)

for line in other_lines:
    print(line)

if any(line.strip() for line in other_lines):
    print("markdownlint exited non-zero with unclassified output; failing safe.")
    sys.exit(2)

print("No blocking markdown issues on changed lines.")
PY
SCRIPT_EXIT=$?
set -e

cat "$FILTERED_OUTPUT_FILE"

rm -f "$LINT_OUTPUT_FILE" "$CHANGED_LINES_JSON_FILE" "$FILTERED_OUTPUT_FILE"
exit "$SCRIPT_EXIT"
