#!/usr/bin/env python3
"""Summarize DBNames-Ext records by extension inventory and XML match status."""

from __future__ import annotations

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


def load_json(path: Path) -> dict[str, Any]:
    return json.loads(path.read_text(encoding="utf-8"))


def main() -> int:
    parser = argparse.ArgumentParser(description="Summarize extension DBNames records.")
    parser.add_argument("--dbnames", type=Path, required=True)
    parser.add_argument("--compare", type=Path, required=True)
    parser.add_argument("--inventory", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()

    dbnames = load_json(args.dbnames)
    compare = load_json(args.compare)
    inventory = load_json(args.inventory)

    extension_by_file = {}
    for extension in inventory.get("extensions") or []:
        file_name = extension.get("dbnames_ext_file_name")
        if file_name:
            extension_by_file[file_name] = extension

    unmatched_guid_set = set(compare.get("unmatched_sql_guids") or [])
    matched_guid_set = set(compare.get("matched_guids") or [])
    unmatched_by_guid = {item["guid"]: item for item in compare.get("unmatched_sql") or []}
    if not unmatched_guid_set:
        unmatched_guid_set = set(unmatched_by_guid)
    if not matched_guid_set:
        matched_guid_set = {item["guid"] for item in compare.get("matches") or []}

    summaries: dict[str, Any] = {}
    for dbnames_file in dbnames.get("dbnames") or []:
        file_name = dbnames_file.get("file_name")
        if not str(file_name).startswith("DBNames-Ext-"):
            continue
        extension = extension_by_file.get(file_name)
        key = file_name
        item = summaries.setdefault(
            key,
            {
                "dbnames_ext_file": file_name,
                "extension_name": extension.get("extension_name") if extension else None,
                "extension_guid": extension.get("dbnames_ext_guid") if extension else None,
                "extension_order": extension.get("extension_order") if extension else None,
                "record_count": 0,
                "guid_count": 0,
                "matched_guid_count": 0,
                "unmatched_guid_count": 0,
                "storage_role_counts": Counter(),
                "matched_storage_role_counts": Counter(),
                "unmatched_storage_role_counts": Counter(),
                "unmatched_examples": [],
            },
        )
        seen_guids = set()
        for record in dbnames_file.get("records") or []:
            if record.get("status") != "parsed":
                continue
            guid = record.get("guid")
            role = record.get("storage_role")
            item["record_count"] += 1
            item["storage_role_counts"][role] += 1
            if guid not in seen_guids:
                seen_guids.add(guid)
                item["guid_count"] += 1
                if guid in matched_guid_set:
                    item["matched_guid_count"] += 1
                elif guid in unmatched_guid_set:
                    item["unmatched_guid_count"] += 1
                    if len(item["unmatched_examples"]) < 20:
                        item["unmatched_examples"].append(
                            {
                                "guid": guid,
                                "storage_roles": (unmatched_by_guid.get(guid) or {}).get("storage_roles"),
                                "records": (unmatched_by_guid.get(guid) or {}).get("records", [])[:5],
                            }
                        )
                else:
                    item["unmatched_guid_count"] += 1
            if guid in matched_guid_set:
                item["matched_storage_role_counts"][role] += 1
            else:
                item["unmatched_storage_role_counts"][role] += 1

    output_items = []
    for item in summaries.values():
        output_items.append(
            {
                **{
                    key: value
                    for key, value in item.items()
                    if not key.endswith("_counts") and key != "unmatched_examples"
                },
                "storage_role_counts": dict(item["storage_role_counts"].most_common()),
                "matched_storage_role_counts": dict(item["matched_storage_role_counts"].most_common()),
                "unmatched_storage_role_counts": dict(item["unmatched_storage_role_counts"].most_common()),
                "unmatched_examples": item["unmatched_examples"],
            }
        )
    output_items.sort(key=lambda row: (-row["unmatched_guid_count"], row["dbnames_ext_file"]))

    result = {
        "schema": "onec_extension_dbnames_summary.v1",
        "dbnames": str(args.dbnames),
        "compare": str(args.compare),
        "inventory": str(args.inventory),
        "extension_file_count": len(output_items),
        "extensions": output_items,
    }
    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(
            {
                "output": str(args.output),
                "extension_files": len(output_items),
                "total_unmatched_guids": sum(item["unmatched_guid_count"] for item in output_items),
            },
            ensure_ascii=False,
        )
    )
    return 0


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