"""Offline synthetic used-electronics cohort. No network calls or live valuations."""
from collections import Counter
from decimal import Decimal, InvalidOperation
from statistics import median


def summarize(rows, reviews, currency="USD"):
    amounts, seen, excluded = [], set(), Counter()
    for row in rows:
        item_id = row.get("itemId")
        if not item_id:
            excluded["missing_id"] += 1
            continue
        if item_id in seen:
            excluded["duplicate_id"] += 1
            continue
        seen.add(item_id)
        decision = reviews.get(item_id, {}).get("decision", "hold")
        if decision != "include":
            excluded["review_" + decision] += 1
            continue
        if row.get("listingType") != "sold" or row.get("soldCurrency") != currency:
            excluded["population_or_currency"] += 1
            continue
        if row.get("quality", {}).get("priceBasis") != "displayed_listing_price":
            excluded["price_basis"] += 1
            continue
        try:
            amount = Decimal(str(row.get("soldPrice")))
        except (InvalidOperation, ValueError):
            excluded["invalid_amount"] += 1
            continue
        if not amount.is_finite() or amount < 0:
            excluded["invalid_amount"] += 1
            continue
        amounts.append(amount)
    amounts.sort()
    n = len(amounts)
    result = {"count": n, "median": median(amounts) if n else None,
              "q1": None, "q3": None, "iqr": None, "excluded": dict(excluded)}
    if n >= 4:
        q1, q3 = median(amounts[:n // 2]), median(amounts[(n + 1) // 2:])
        result.update(q1=q1, q3=q3, iqr=q3 - q1)
    return result


def row(item_id, amount, currency="USD", basis="displayed_listing_price"):
    return {"itemId": item_id, "listingType": "sold", "soldPrice": amount,
            "soldCurrency": currency, "quality": {"priceBasis": basis,
            "acceptedOfferAmount": None, "saleDateVerified": False,
            "exactProductMatchVerified": False}}


if __name__ == "__main__":
    rows = [row(f"S{i}", str(amount)) for i, amount in enumerate([100, 120, 140, 160, 180, 200])]
    reviews = {item["itemId"]: {"decision": "include", "reason": "Synthetic complete target device"} for item in rows}
    rows += [row("PART", "12"), row("HOLD", "80"), row("RANGE", "60", basis="range_lower_bound"),
             row("EUR", "90", currency="EUR"), row("BAD", "NaN"), rows[0]]
    reviews.update({"PART": {"decision": "exclude", "reason": "Replacement part"},
                    "RANGE": {"decision": "include"}, "EUR": {"decision": "include"},
                    "BAD": {"decision": "include"}})
    result = summarize(rows, reviews)
    assert result["count"] == 6 and result["median"] == Decimal("150")
    assert (result["q1"], result["q3"], result["iqr"]) == (Decimal("120"), Decimal("180"), Decimal("60"))
    assert result["excluded"] == {"review_exclude": 1, "review_hold": 1, "price_basis": 1,
                                   "population_or_currency": 1, "invalid_amount": 1, "duplicate_id": 1}
    assert summarize([], {})["median"] is None
    assert summarize([row("S0", "100")], reviews)["iqr"] is None
    odd = summarize([row(f"O{i}", str(v)) for i, v in enumerate([1, 2, 3, 4, 5])],
                    {f"O{i}": {"decision": "include"} for i in range(5)})
    assert odd["q1"] == Decimal("1.5") and odd["q3"] == Decimal("4.5")
    print("SYNTHETIC EXAMPLE ONLY; amounts are not live market observations.")
    print(f"Accepted n={result['count']}; displayed item-price median USD {result['median']:.2f}")
    print(f"Q1 USD {result['q1']:.2f}; Q3 USD {result['q3']:.2f}; IQR USD {result['iqr']:.2f}")
    print("Excluded:", result["excluded"])
