"""Filename inference, labels and identity tuples — and the rule that the
browser's copy of them (`ui/src/metadata.js`) agrees with the server's. One
case list drives both: the Python assertions run it directly, and one test
feeds the same list through node importing the ESM module, so a rule changed
on one side fails here until the other side moves."""

import json
import shutil
import subprocess
from pathlib import Path

import pytest

from quber.playground.metadata import (
    annotate_overlaps,
    export_stem,
    filing_label,
    infer,
    overlap_key,
    tuple_key,
)

METADATA_JS = Path(__file__).parents[2] / "src" / "quber" / "playground" / "ui" / "src" / "metadata.js"

# (filename, filing_type, year, period) — drawn from the corpus's real names.
INFER_CASES = [
    ("SEVN_Q126_10Q.pdf", "10-Q", 2026, "Q1"),
    ("acr-1q2026-earnings-presentation-final.pdf", "99-2", 2026, "Q1"),
    ("lft-2026q1-supplemental.pdf", "99-2", 2026, "Q1"),
    ("kref-q1-26-earnings-release.pdf", "99-2", 2026, "Q1"),
    ("kref-q2-26-supplemental.pdf", "99-2", 2026, "Q2"),
    ("Ladder-Capital-Investor-Presentation-2026-07-23.pdf", "99-2", 2026, None),
    ("3M_2018_10K.pdf", "10-K", 2018, "FY"),
    ("sevn-q2-2026-press-release.pdf", "99-1", 2026, "Q2"),
    ("visa-991-q126.pdf", "99-1", 2026, "Q1"),
    ("brsp-full-year-2025-results.pdf", None, 2025, "FY"),
    ("first-half-2026-update.pdf", None, 2026, "H1"),
    ("kref-q2-26-10.pdf", None, 2026, "Q2"),
    ("statement.pdf", None, None, None),
]


@pytest.mark.parametrize("filename,filing_type,year,period", INFER_CASES)
def test_infer(filename, filing_type, year, period):
    assert infer(filename) == {"filing_type": filing_type, "year": year, "period": period}


def test_infer_strips_directory_and_uri_prefixes():
    assert infer("s3://bucket/family/SEVN_Q126_10Q.pdf")["filing_type"] == "10-Q"


def test_js_twin_agrees_on_every_case():
    node = shutil.which("node")
    if node is None:
        pytest.skip("node is not installed")
    script = (
        f"import {{ infer, filingLabel, tupleKey }} from {json.dumps(METADATA_JS.as_uri())};\n"
        f"const cases = {json.dumps([c[0] for c in INFER_CASES])};\n"
        "console.log(JSON.stringify({\n"
        "  inferred: cases.map((c) => infer(c)),\n"
        '  label: filingLabel({ filing_type: "10-K", year: 2025, period: "FY", version: 2 }),\n'
        "  emptyLabel: filingLabel({ filing_type: null, year: null, period: null, version: null }),\n"
        '  key: tupleKey({ folder: "LFT", filing_type: "99-2", year: 2026, period: "Q1", version: null }),\n'
        '  keyCased: tupleKey({ folder: "lft", filing_type: "99-2", year: 2026, period: "q1", version: null }),\n'
        '  noKey: tupleKey({ folder: "LFT", filing_type: null, year: 2026, period: "Q1", version: null }),\n'
        "}));\n"
    )
    out = subprocess.run(
        [node, "--input-type=module", "-e", script], capture_output=True, text=True, check=True
    )
    js = json.loads(out.stdout)
    for (filename, filing_type, year, period), got in zip(INFER_CASES, js["inferred"], strict=True):
        assert got == {"filing_type": filing_type, "year": year, "period": period}, filename
    assert js["label"] == filing_label("10-K", 2025, "FY", 2)
    assert js["emptyLabel"] == filing_label(None, None, None, None)
    assert js["key"] == js["keyCased"] and js["key"] is not None
    assert js["noKey"] is None


def test_filing_label_omits_missing_parts():
    assert filing_label("99-2", 2026, "Q1", None) == "99-2 · Q1 2026"
    assert filing_label("10-K", 2025, "FY", 2) == "10-K · FY 2025 · v2"
    assert filing_label(None, 2026, None, None) == "2026"
    assert filing_label(None, None, None, None) == ""


def test_export_stem_falls_back_down_the_precedence():
    assert export_stem("99-2 · Q1 2026", "Title", "file.pdf") == "99-2-q1-2026"
    assert export_stem("", "Q1 Earnings!", "file.pdf") == "q1-earnings"
    assert export_stem(None, "", "My File.pdf") == "my-file-pdf"
    assert export_stem(None, None, None) == "document"


def test_tuple_key_needs_all_three_and_compares_case_insensitively():
    assert tuple_key("LFT", "99-2", 2026, "Q1", None) == ("lft", "99-2", 2026, "q1", None)
    assert tuple_key("LFT", "99-2", 2026, "Q1", None) == tuple_key("lft", "99-2", 2026, "q1", None)
    assert tuple_key(None, "99-2", 2026, "Q1", 2) == ("", "99-2", 2026, "q1", 2)
    assert tuple_key("LFT", None, 2026, "Q1", None) is None
    assert tuple_key("LFT", "99-2", None, "Q1", None) is None
    assert tuple_key("LFT", "99-2", 2026, None, None) is None


def test_overlap_key_excludes_the_version():
    assert overlap_key("LFT", "99-2", 2026, "Q1") == ("lft", "99-2", 2026, "q1")
    assert overlap_key("LFT", None, 2026, "Q1") is None


def test_annotate_overlaps_flags_versionless_tuple_sharers_only():
    docs = [
        {"folder": "LFT", "filing_type": "99-2", "year": 2026, "period": "Q1", "version": 1},
        {"folder": "lft", "filing_type": "99-2", "year": 2026, "period": "q1", "version": 2},
        {"folder": "LFT", "filing_type": "10-Q", "year": 2026, "period": "Q1"},
        {"folder": "LFT", "filing_type": None, "year": 2026, "period": "Q1"},
        {"folder": "ACR", "filing_type": None, "year": None, "period": None},
    ]
    annotate_overlaps(docs)
    assert [d["overlap"] for d in docs] == [True, True, False, False, False]
