"""
Pure comparison logic for the LE Capital -> DealerKit funding sync, added
2026-08-24 (Mark: "LE captial is the source of truth as this is the funding
platform, i need DK funding to match the LE portal", then "add a daily
automation to check funding status and add or settle the funding status on
DK, this can be done using this page ... 'current stock' and 'Stock
History' exports"). Kept separate from bidbrain/dealerkit_write.py (the
live browser automation that actually adds and settles records) and
bidbrain/readers/lecapital.py (the live page reading), so the actual
decision making, what needs adding, what needs settling, can be tested
without a browser at all.

LE Capital is treated as the source of truth throughout: a car it still
shows as actively funded (Current Stock) but DealerKit does not have, or
has marked settled, is a real gap to fix. A car LE Capital shows as settled
(Stock History) but DealerKit still shows live is settled here too. A
funded_value disagreement on a car both sides already agree is live is
never auto corrected, only flagged, same conservative stance already used
elsewhere in this project for a value disagreement (see CLAUDE.md,
HG17NRF's Assurance/Indemnity Fee note).
"""


def _add_months(date_iso, months):
    """date_iso is a "YYYY-MM-DD" string. Every real DealerKit funding
    record on this account runs a fixed term (plan_starts_at plus N
    calendar months exactly, proven live against EY69KYV: plan start
    2026-05-01, expiry 2026-09-01, four months later to the day), so a new
    record's own expiry is always computed this way rather than trusted to
    DealerKit's own default (found live to fill in about 8 months out,
    wrong, see add_funding_record's own docstring in dealerkit_write.py)."""
    y, m, d = (int(x) for x in date_iso.split("-"))
    total = (y * 12 + (m - 1)) + months
    y2, m2 = divmod(total, 12)
    return f"{y2:04d}-{m2 + 1:02d}-{d:02d}"


def plan_sync(le_current, le_history, dk_funding, funded_term_months=4):
    """le_current: bidbrain.readers.lecapital.read_current_stock's own
    return shape (reg, funded_value, plan_starts_at, ...). le_history:
    read_stock_history's own shape (reg, funded_value, plan_starts_at,
    settled_on, ...). dk_funding: dealerkit_write.read_dk_funding_list's
    own shape (reg, funding_status, funded_value, plan_starts_at,
    funding_settled_at).

    Returns {"to_add": [...], "to_settle": [...], "mismatched": [...]}.
    to_add: dicts with reg, funded_value, plan_starts_at,
    funding_expires_at, ready to pass straight to add_funding_record.
    to_settle: dicts with reg, settled_on, ready to pass straight to
    settle_funding_record.
    mismatched: regs live on both sides with a real funded_value
    difference, never auto corrected, just surfaced for Mark's own look.
    """
    dk_by_reg = {r["reg"]: r for r in dk_funding}

    to_add = []
    for car in le_current:
        reg = car["reg"]
        existing = dk_by_reg.get(reg)
        if existing is None:
            to_add.append({
                "reg": reg,
                "funded_value": car["funded_value"],
                "plan_starts_at": car["plan_starts_at"],
                "funding_expires_at": _add_months(car["plan_starts_at"], funded_term_months),
            })
        # A car LE Capital still shows as live but DealerKit already has
        # marked settled is a genuine disagreement between the two
        # systems, never silently reopened here, left for a human, same
        # as a value mismatch.

    to_settle = []
    for car in le_history:
        reg = car["reg"]
        existing = dk_by_reg.get(reg)
        if existing is not None and existing.get("funding_status") == "live" \
                and not existing.get("funding_settled_at"):
            to_settle.append({"reg": reg, "settled_on": car["settled_on"]})

    mismatched = []
    for car in le_current:
        existing = dk_by_reg.get(car["reg"])
        if existing is not None and existing.get("funded_value") is not None \
                and abs(existing["funded_value"] - car["funded_value"]) > 0.01:
            mismatched.append({
                "reg": car["reg"],
                "le_capital_value": car["funded_value"],
                "dealerkit_value": existing["funded_value"],
            })

    return {"to_add": to_add, "to_settle": to_settle, "mismatched": mismatched}
