from __future__ import annotations

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

import yaml

from one_c_its_platform import parse_doc_coordinate, platform_doc_id_from_url


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_START_LINKS = ROOT / "plugins" / "1c" / "rag" / "official-docs" / "start-links.json"
DEFAULT_SOURCES = ROOT / "plugins" / "1c" / "rag" / "official-docs" / "sources.yaml"
DEFAULT_OUTPUT = ROOT / "plugins" / "1c" / "rag" / "official-docs" / "platform-versions.json"


def load_json(path: Path) -> dict[str, Any]:
    if not path.exists():
        return {}
    data = json.loads(path.read_text(encoding="utf-8-sig"))
    return data if isinstance(data, dict) else {}


def load_yaml(path: Path) -> dict[str, Any]:
    if not path.exists():
        return {}
    data = yaml.safe_load(path.read_text(encoding="utf-8"))
    return data if isinstance(data, dict) else {}


def version_key(value: str | None) -> tuple[int, int, int, str]:
    if not value or value == "8.x":
        return (8, -1, -1, value or "")
    parts = value.split(".")
    numeric = []
    for part in parts[:3]:
        try:
            numeric.append(int(part))
        except ValueError:
            numeric.append(-1)
    while len(numeric) < 3:
        numeric.append(-1)
    return (numeric[0], numeric[1], numeric[2], value)


def version_from_title(title: str) -> str | None:
    import re

    match = re.search(r"\b(\d+\.\d+(?:\.\d+)?)\b", title)
    return match.group(1) if match else None


def best_platform_version(coord: dict[str, str | None], title: str) -> str | None:
    version = coord.get("platform_version")
    if version == "8.x":
        return version_from_title(title) or version
    return version or version_from_title(title)


def build_catalog(start_links_path: Path, sources_path: Path) -> dict[str, Any]:
    start_links = load_json(start_links_path)
    sources_config = load_yaml(sources_path)
    active_by_doc_id: dict[str, list[dict[str, Any]]] = {}
    for source in sources_config.get("sources") or []:
        url = str(source.get("url") or "")
        doc_id = platform_doc_id_from_url(url)
        if not doc_id:
            continue
        active_by_doc_id.setdefault(doc_id, []).append(
            {
                "source_id": source.get("id"),
                "title": source.get("title"),
                "url": url,
                "source_type": source.get("source_type"),
            }
        )

    versions_by_doc_id: dict[str, dict[str, Any]] = {}
    for item in start_links.get("start_links") or []:
        url = str(item.get("url") or "")
        coord = parse_doc_coordinate(url)
        doc_id = coord.get("platform_doc_id")
        if not doc_id:
            continue
        title = str(item.get("text") or "")
        record = versions_by_doc_id.setdefault(
            doc_id,
            {
                "platform_doc_id": doc_id,
                "platform_version": best_platform_version(coord, title),
                "url": url,
                "title": title,
                "category": item.get("category"),
                "active": False,
                "active_sources": [],
            },
        )
        record["title"] = record.get("title") or item.get("text") or ""
        record["category"] = record.get("category") or item.get("category")

    for doc_id, sources in active_by_doc_id.items():
        coord = parse_doc_coordinate(sources[0]["url"])
        title = str(sources[0].get("title") or "")
        record = versions_by_doc_id.setdefault(
            doc_id,
            {
                "platform_doc_id": doc_id,
                "platform_version": best_platform_version(coord, title),
                "url": sources[0]["url"],
                "title": title,
                "category": "platform_doc",
                "active": False,
                "active_sources": [],
            },
        )
        record["active"] = True
        record["active_sources"] = sources

    versions = sorted(versions_by_doc_id.values(), key=lambda item: version_key(item.get("platform_version")), reverse=True)
    active_versions = [item for item in versions if item.get("active")]
    latest_8_3 = next((item for item in versions if str(item.get("platform_version") or "").startswith("8.3.")), None)
    latest_active_8_3 = next((item for item in active_versions if str(item.get("platform_version") or "").startswith("8.3.")), None)
    return {
        "schema": "onec_its_platform_versions.v1",
        "created_at_unix": int(time.time()),
        "sources": {
            "start_links": str(start_links_path),
            "sources_yaml": str(sources_path),
        },
        "counts": {
            "versions": len(versions),
            "active_versions": len(active_versions),
        },
        "defaults": {
            "latest_discovered_8_3": latest_8_3,
            "latest_active_8_3": latest_active_8_3,
        },
        "versions": versions,
    }


def main() -> int:
    parser = argparse.ArgumentParser(description="Build a version catalog for 1C:ITS platform documentation.")
    parser.add_argument("--start-links", type=Path, default=DEFAULT_START_LINKS)
    parser.add_argument("--sources", type=Path, default=DEFAULT_SOURCES)
    parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT)
    parser.add_argument("--print", action="store_true", dest="print_report")
    args = parser.parse_args()

    report = build_catalog(args.start_links, args.sources)
    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")
    payload = report if args.print_report else {"output": str(args.output), "counts": report["counts"], "defaults": report["defaults"]}
    print(json.dumps(payload, ensure_ascii=False, indent=2))
    return 0


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