#!/usr/bin/env python3
"""Compare two OpenAPI documents by normalized HTTP method and path."""

from __future__ import annotations

import argparse
import csv
import json
from pathlib import Path
from typing import Any


HTTP_METHODS = {"delete", "get", "head", "options", "patch", "post", "put", "trace"}


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--legacy", required=True, type=Path, help="Legacy OpenAPI JSON")
    parser.add_argument("--target", required=True, type=Path, help="Target OpenAPI JSON")
    parser.add_argument("--output", required=True, type=Path, help="Output CSV")
    return parser.parse_args()


def load_operations(path: Path) -> dict[tuple[str, str], dict[str, str]]:
    with path.open(encoding="utf-8") as source:
        document: dict[str, Any] = json.load(source)

    operations: dict[tuple[str, str], dict[str, str]] = {}
    for route, path_item in document.get("paths", {}).items():
        if not isinstance(path_item, dict):
            continue
        for method, operation in path_item.items():
            normalized_method = method.lower()
            if normalized_method not in HTTP_METHODS or not isinstance(operation, dict):
                continue
            operations[(normalized_method.upper(), route)] = {
                "operation_id": str(operation.get("operationId", "")),
                "summary": str(operation.get("summary", "")),
            }
    return operations


def main() -> None:
    args = parse_args()
    legacy = load_operations(args.legacy)
    target = load_operations(args.target)
    keys = sorted(legacy.keys() | target.keys(), key=lambda key: (key[1], key[0]))

    args.output.parent.mkdir(parents=True, exist_ok=True)
    with args.output.open("w", encoding="utf-8", newline="") as destination:
        writer = csv.DictWriter(
            destination,
            fieldnames=(
                "method",
                "path",
                "status",
                "legacy_operation_id",
                "legacy_summary",
                "target_operation_id",
                "target_summary",
            ),
            lineterminator="\n",
        )
        writer.writeheader()
        for method, route in keys:
            legacy_operation = legacy.get((method, route), {})
            target_operation = target.get((method, route), {})
            status = (
                "exact_match"
                if legacy_operation and target_operation
                else "legacy_only"
                if legacy_operation
                else "target_only"
            )
            writer.writerow(
                {
                    "method": method,
                    "path": route,
                    "status": status,
                    "legacy_operation_id": legacy_operation.get("operation_id", ""),
                    "legacy_summary": legacy_operation.get("summary", ""),
                    "target_operation_id": target_operation.get("operation_id", ""),
                    "target_summary": target_operation.get("summary", ""),
                }
            )

    exact_matches = len(legacy.keys() & target.keys())
    print(
        f"legacy={len(legacy)} target={len(target)} exact={exact_matches} "
        f"legacy_only={len(legacy) - exact_matches} target_only={len(target) - exact_matches}"
    )


if __name__ == "__main__":
    main()
