#!/usr/bin/env python3
"""Index exported 1C ConfigCAS files for GUID/string lookup.

This is a mechanical content index: decompress, decode when possible, collect
GUIDs and string hits. It does not infer semantic object kinds.
"""

from __future__ import annotations

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

from inspect_1c_sql_files import GUID_RE, try_decode, try_decompress


def inspect_cas_file(path: Path, target_guids: set[str], target_strings: list[str]) -> dict[str, Any]:
    data = path.read_bytes()
    payload, compression = try_decompress(data)
    text, encoding = try_decode(payload)
    item: dict[str, Any] = {
        "file_name": path.name,
        "bytes": len(data),
        "payload_bytes": len(payload),
        "compression": compression,
        "encoding": encoding,
        "guid_count": 0,
        "target_guid_hits": [],
        "target_string_hits": [],
        "guids_sample": [],
        "text_preview": "",
    }
    if text is None:
        return item
    clean = text.replace("\x00", "").replace("\ufeff", "")
    guids = sorted(set(match.lower() for match in GUID_RE.findall(clean)))
    item["guid_count"] = len(guids)
    item["guids_sample"] = guids[:50]
    item["target_guid_hits"] = sorted(target_guids.intersection(guids))
    item["target_string_hits"] = [value for value in target_strings if value and value in clean]
    if item["target_guid_hits"] or item["target_string_hits"]:
        item["text_preview"] = clean[:2000]
    else:
        item["text_preview"] = clean[:300]
    return item


def main() -> int:
    parser = argparse.ArgumentParser(description="Index exported ConfigCAS files.")
    parser.add_argument("cas_dir", type=Path)
    parser.add_argument("--output", type=Path, required=True)
    parser.add_argument("--target-guid", action="append", default=[])
    parser.add_argument("--target-string", action="append", default=[])
    args = parser.parse_args()

    target_guids = {value.lower() for value in args.target_guid}
    files = sorted(path for path in args.cas_dir.iterdir() if path.is_file())
    items = [inspect_cas_file(path, target_guids, args.target_string) for path in files]
    guid_hits = [item for item in items if item["target_guid_hits"]]
    string_hits = [item for item in items if item["target_string_hits"]]
    compression_counts: dict[str, int] = {}
    encoding_counts: dict[str, int] = {}
    for item in items:
        compression_counts[item["compression"]] = compression_counts.get(item["compression"], 0) + 1
        encoding = item["encoding"] or "<binary>"
        encoding_counts[encoding] = encoding_counts.get(encoding, 0) + 1
    report = {
        "schema": "onec_sql_cas_index.v1",
        "cas_dir": str(args.cas_dir),
        "file_count": len(items),
        "target_guids": sorted(target_guids),
        "target_strings": args.target_string,
        "compression_counts": dict(sorted(compression_counts.items())),
        "encoding_counts": dict(sorted(encoding_counts.items())),
        "target_guid_hit_count": len(guid_hits),
        "target_string_hit_count": len(string_hits),
        "target_guid_hits": guid_hits,
        "target_string_hits": string_hits,
        "files": items,
    }
    args.output.parent.mkdir(parents=True, exist_ok=True)
    args.output.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    print(
        json.dumps(
            {
                "output": str(args.output),
                "files": len(items),
                "guid_hits": len(guid_hits),
                "string_hits": len(string_hits),
                "compression_counts": report["compression_counts"],
            },
            ensure_ascii=False,
        )
    )
    return 0


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