"""``fedres-validate`` — validate fed-resources documents + live NDJSON wire streams.

Fail-closed: an unreadable file, malformed JSON, an unknown ``schema_version``/``v``,
or any schema violation is a nonzero exit. ``.ndjson`` files are validated line by line.
"""

from __future__ import annotations

import json
import sys
from pathlib import Path

from ._schemas import validate_payload


def validate_file(path: Path) -> list[str]:
    """Return a list of human-readable errors for one file ([] == valid)."""
    text = path.read_text(encoding="utf-8")
    if path.suffix == ".ndjson":
        errors: list[str] = []
        for lineno, raw in enumerate(text.splitlines(), start=1):
            line = raw.strip()
            if not line:
                continue
            try:
                payload = json.loads(line)
            except json.JSONDecodeError as exc:
                errors.append(f"line {lineno}: invalid JSON: {exc}")
                continue
            errors.extend(f"line {lineno}: {err}" for err in validate_payload(payload))
        return errors
    try:
        payload = json.loads(text)
    except json.JSONDecodeError as exc:
        return [f"invalid JSON: {exc}"]
    return validate_payload(payload)


def main(argv: list[str] | None = None) -> int:
    args = list(sys.argv[1:] if argv is None else argv)
    if not args:
        print("usage: fedres-validate <file.json|file.ndjson> ...", file=sys.stderr)
        return 2
    total = 0
    for arg in args:
        path = Path(arg)
        if not path.exists():
            print(f"FAIL {arg}: no such file", file=sys.stderr)
            total += 1
            continue
        errors = validate_file(path)
        if errors:
            total += len(errors)
            print(f"FAIL {arg}")
            for err in errors:
                print(f"  - {err}")
        else:
            print(f"ok   {arg}")
    if total:
        print(f"\n{total} validation error(s)", file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":  # pragma: no cover
    raise SystemExit(main())
