#!/usr/bin/env python3
"""Плановые доходы Марса → плановые операции Финтабло (income, isPlan=1).

Одна операция на СТРОКУ в месяц (девять строк, не мелко — B2B/события одной суммой).
Структура строк = канон income_lines.LINES (slug'и совпадают, читает тот же справочник report.py).
Идемпотентно: externalId `plansync:income:{MM.YYYY}:{slug}` — повторный занос ПЕРЕЗАПИШЕТ (delete+create), не задвоит.

Строки (slug → статья Финтабло) — см. income_lines.py:
  uroki, gruppy, hor, arenda, iventy, cover, podpiska, prochee → Выручка b2c (1543079)
  b2b                                                          → Выручка b2b (1543085)

Запуск:
  python3 plan_income.py 08.2026 uroki=2500000 arenda=600000 b2b=400000              # dry-run
  python3 plan_income.py 08.2026 uroki=2500000 ... --commit                          # запись
  python3 plan_income.py 08.2026 --show                                              # что сейчас в плане
Указывай только те строки, что меняешь — остальные не трогаются.
"""
import sys, json, calendar, re
import core
import income_lines as il

CAT_B2C = il.CAT_B2C
CAT_B2B = il.CAT_B2B
MONEYBAG = 151784   # Точка *1195 (для плана счёт не критичен)

# slug → (описание операции, статья Финтабло). Справочник живёт в income_lines.
LINES = {l.slug: ("%s — план" % l.name, l.category) for l in il.LINES}


money = core.money
ftreq = core.ftmut   # POST без ретраев, DELETE с ретраями (см. core.ftmut)


def existing_income_plan(mm):
    """{slug: (id, value)} — уже занесённые плановые income-строки месяца mm."""
    prefix = f"plansync:income:{mm}:"
    last = calendar.monthrange(int(mm[3:]), int(mm[:2]))[1]
    out = {}
    for t in core.ft_all("/v1/transaction", group="income",
                         dateFrom=f"01.{mm}", dateTo=f"{last}.{mm}"):
        ext = t.get("externalId") or ""
        if t.get("isPlan") and ext.startswith(prefix):
            out[ext[len(prefix):]] = (t.get("id"), float(t.get("value") or 0))
    return out


def main():
    args = sys.argv[1:]
    if not args:
        print(__doc__); return
    mm = args[0]
    if not re.match(r"\d{2}\.\d{4}$", mm):
        print(f"⚠️ первый аргумент — месяц MM.YYYY, получено «{mm}»"); return
    commit = "--commit" in args
    show = "--show" in args
    pairs = {}
    for a in args[1:]:
        if "=" in a:
            k, v = a.split("=", 1)
            if k not in LINES:
                print(f"⚠️ неизвестная строка '{k}'. Доступны: {', '.join(LINES)}"); return
            pairs[k] = float(v.replace(" ", "").replace("_", ""))

    mm_last = calendar.monthrange(int(mm[3:]), int(mm[:2]))[1]
    plan_date = f"28.{mm}" if mm_last >= 28 else f"{mm_last}.{mm}"
    cur = existing_income_plan(mm)

    if show or not pairs:
        print(f"\nПлан доходов {mm} (сейчас в Финтабло):")
        tot = 0.0
        for slug, (name, _) in LINES.items():
            v = cur.get(slug, (None, 0))[1]
            tot += v
            print(f"  {slug:12} {money(v):>12}  {name}")
        print(f"  {'ИТОГО':12} {money(tot):>12}")
        if not pairs:
            return

    print(f"\n{'ЗАПИСЬ' if commit else 'DRY-RUN'} · план доходов {mm} · дата операций {plan_date}")
    if commit:   # журнал до мутаций — чтобы сбой посреди delete+create не потерял строки молча
        import os
        exp = os.path.join(os.path.dirname(os.path.abspath(__file__)), "exports")
        os.makedirs(exp, exist_ok=True)
        jpath = os.path.join(exp, f"planincome_journal_{mm.replace('.','-')}.json")
        with open(jpath, "w", encoding="utf-8") as jf:
            json.dump({"month": mm, "old": {s: cur.get(s) for s in pairs}, "new": pairs}, jf, ensure_ascii=False, indent=1)
    for slug, val in pairs.items():
        name, cat = LINES[slug]
        old = cur.get(slug)
        act = f"{money(old[1])} → {money(val)}" if old else f"новая {money(val)}"
        print(f"  {slug:12} {act}")
        if commit:
            if old:
                ftreq("DELETE", f"/v1/transaction/{old[0]}")
            ftreq("POST", "/v1/transaction", dict(
                value=val, group="income", moneybagId=MONEYBAG, date=plan_date, factMonth=mm,
                categoryId=cat, isPlan=1, description=name, externalId=f"plansync:income:{mm}:{slug}"))
    if commit:
        print("✅ записано. Проверь: python3 plan_income.py", mm, "--show")
    else:
        print("— это dry-run. Добавь --commit для записи.")


if __name__ == "__main__":
    main()
