from __future__ import annotations

import argparse
import json
import re
import sys
from pathlib import Path

import yaml


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_POLICY = ROOT / "plugins" / "1c" / "connector" / "policies" / "read-only-query.yaml"


def load_policy(path: Path) -> dict:
    with path.open("r", encoding="utf-8") as handle:
        data = yaml.safe_load(handle)
    if not isinstance(data, dict):
        raise ValueError(f"{path} must contain a YAML mapping")
    return data


def validate_query(query: str, policy: dict) -> list[str]:
    errors = []
    normalized = query.strip()
    if not normalized:
        return ["query is empty"]
    if not re.match(r"(?is)^\s*(ВЫБРАТЬ|SELECT)\b", normalized):
        errors.append("only SELECT/ВЫБРАТЬ queries are allowed")
    for pattern in policy.get("deny_patterns") or []:
        if re.search(pattern, normalized):
            errors.append(f"query matches denied pattern: {pattern}")
    return errors


def main() -> int:
    parser = argparse.ArgumentParser(description="Validate a read-only 1C query request.")
    parser.add_argument("--query")
    parser.add_argument("--request-json", type=Path)
    parser.add_argument("--policy", type=Path, default=DEFAULT_POLICY)
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args()

    if args.request_json:
        request = json.loads(args.request_json.read_text(encoding="utf-8"))
        query = request.get("query") or ""
    else:
        query = args.query or ""

    policy = load_policy(args.policy)
    errors = validate_query(query, policy)
    result = {
        "allowed": not errors,
        "errors": errors,
        "limits": policy.get("limits") or {},
    }
    if args.json:
        print(json.dumps(result, ensure_ascii=False, indent=2))
    elif errors:
        print("Query is denied:", file=sys.stderr)
        for error in errors:
            print(f"- {error}", file=sys.stderr)
    else:
        print("Query is allowed.")
    return 0 if not errors else 1


if __name__ == "__main__":
    raise SystemExit(main())
