#!/usr/bin/env python3
from __future__ import annotations

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


def load_entries(path: Path) -> list[dict[str, Any]]:
    report = json.loads(path.read_text(encoding="utf-8"))
    matrix = report.get("matrix") if isinstance(report.get("matrix"), dict) else report
    entries = matrix.get("entries") if isinstance(matrix.get("entries"), list) else []
    return [entry for entry in entries if isinstance(entry, dict)]


def target_map(entries: list[dict[str, Any]]) -> dict[tuple[str, str, str], dict[str, Any]]:
    result: dict[tuple[str, str, str], dict[str, Any]] = {}
    for entry in entries:
        target = entry.get("requested_target") if isinstance(entry.get("requested_target"), dict) else {}
        key = (str(target.get("section") or ""), str(target.get("name") or ""), str(target.get("id") or ""))
        if key == ("", "", "") or key in result:
            continue
        result[key] = {field: target.get(field) for field in ("section", "name", "id", "path", "marker", "type_name", "title")}
    return result


def main() -> int:
    parser = argparse.ArgumentParser(description="Compare 1C write matrix reports for structural target moves.")
    parser.add_argument("--before", type=Path, required=True, help="Before write matrix report.")
    parser.add_argument("--after", type=Path, required=True, help="After write matrix report.")
    parser.add_argument("--output", type=Path, required=True, help="Output structural diff JSON path.")
    args = parser.parse_args()

    before_targets = target_map(load_entries(args.before))
    after_targets = target_map(load_entries(args.after))
    moves = []
    for key, after in after_targets.items():
        before = before_targets.get(key)
        if not before:
            continue
        if str(before.get("path") or "") == str(after.get("path") or ""):
            continue
        moves.append(
            {
                "target": {
                    "section": after.get("section"),
                    "name": after.get("name"),
                    "id": after.get("id"),
                    "marker": after.get("marker"),
                    "type_name": after.get("type_name"),
                },
                "old_path": before.get("path"),
                "new_path": after.get("path"),
                "presentation": f"{after.get('name') or after.get('path')}: {before.get('path')} -> {after.get('path')}",
            }
        )
    result = {
        "schema": "onec_form_write_matrix_structural_diff.v1",
        "status": "changed" if moves else "no_changes",
        "before": str(args.before),
        "after": str(args.after),
        "target_moves": moves,
        "counts": {
            "target_moves": len(moves),
            "before_targets": len(before_targets),
            "after_targets": len(after_targets),
        },
    }
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(json.dumps(result, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    print(json.dumps({"schema": result["schema"], "status": result["status"], "counts": result["counts"], "path": str(args.output)}, ensure_ascii=False, indent=2))
    return 0


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