#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Bring every club card into line with the game's own player data.

Two different faults, two different remedies:

  STALE  the card is a real FIFA 17 player but its stored fields are the old
         invented ones (rating derived from nothing, synthetic position, guessed
         club and nation, attributes computed from the rating). REPAIRED in place
         from data/pool.json, which is measured from the game's own database.
         Deleting these would throw away almost the whole club for no reason: the
         name, face and badge are already right, only the numbers are wrong.

  DEAD   the playerid does not exist in the roster at all. The client misses on it
         and stamps its generic card (rating 50, teamid 1933, nation 14, blank
         name). There is nothing to repair, because there is no player to repair it
         to. They are LEFT ALONE unless --delete-dead is passed: removing cards from
         someone's club is their call, not the tool's, and a blank card is ugly
         rather than harmful.

RUN THIS WITH utas_server STOPPED. The server holds the profile in memory and
rewrites it on its own schedule, so an edit made underneath a running server gets
clobbered by the next save. That is exactly what happened on 2026-08-04: nine dead
cards were removed and reappeared a few hours later.

Squad safety: a card referenced by a saved squad is never removed. Repair is safe
for squad members because the item id does not change.

    repair_club.py                       dry run (default)
    repair_club.py --fire                repair stale cards, keep dead ones
    repair_club.py --fire --delete-dead  also remove the unrepairable blanks
"""
import argparse
import json
import os
import shutil
import sys
import time

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from fut_store import STORE                                        # noqa: E402

POOL = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "data", "pool.json")


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--fire", action="store_true")
    ap.add_argument("--delete-dead", action="store_true",
                    help="also remove cards whose playerid is not a real player")
    a = ap.parse_args()

    truth = {p["id"]: p for p in json.load(open(POOL))}
    p = STORE.load()
    items = p.get("items", [])

    squad_ids = set()

    def walk(o):
        if isinstance(o, dict):
            for k, v in o.items():
                if k in ("itemId", "id") and isinstance(v, int):
                    squad_ids.add(v)
                walk(v)
        elif isinstance(o, list):
            for v in o:
                walk(v)

    for key in ("squad", "squads", "squadList"):
        walk(p.get(key))

    repaired, dead, untouched = [], [], 0
    for it in items:
        t = truth.get(it.get("assetId"))
        if not t:
            dead.append(it)
            continue
        changes = []
        if it.get("rating") != t["rating"]:
            changes.append("rating %s->%s" % (it.get("rating"), t["rating"]))
        if it.get("preferredPosition") != t["pos"]:
            changes.append("pos %s->%s" % (it.get("preferredPosition"), t["pos"]))
        if it.get("teamid") != t["team"]:
            changes.append("team %s->%s" % (it.get("teamid"), t["team"]))
        if it.get("nation") != t["nation"]:
            changes.append("nation %s->%s" % (it.get("nation"), t["nation"]))
        if it.get("leagueId") != t["league"]:
            changes.append("league %s->%s" % (it.get("leagueId"), t["league"]))
        if [x.get("value") for x in it.get("attributeList", [])] != t["attrs"]:
            changes.append("attrs")
        if not changes:
            untouched += 1
            continue
        repaired.append((it, changes, t))

    if a.delete_dead:
        keep_dead = [d for d in dead if d.get("id") in squad_ids]
        drop_dead = [d for d in dead if d.get("id") not in squad_ids]
    else:
        keep_dead, drop_dead = dead, []

    print("club %d: %d already correct, %d to repair, %d dead to remove"
          % (len(items), untouched, len(repaired), len(drop_dead)))
    if keep_dead:
        why = ("a squad references them" if a.delete_dead
               else "--delete-dead was not passed")
        print("  %d dead card(s) KEPT (%s)" % (len(keep_dead), why))
    for it, ch, _ in repaired[:8]:
        print("   repair id=%-11s asset=%-7s %s" % (it.get("id"), it.get("assetId"),
                                                    "; ".join(ch)[:80]))
    if len(repaired) > 8:
        print("   ... and %d more" % (len(repaired) - 8))
    for it in drop_dead[:8]:
        print("   remove id=%-11s asset=%s" % (it.get("id"), it.get("assetId")))

    if not a.fire:
        print("\ndry run. Re-run with --fire to write.")
        return 0

    bak = STORE.path + ".bak-repair-%d" % int(time.time())
    shutil.copy(STORE.path, bak)
    print("\nbackup: %s" % bak)

    for it, _, t in repaired:
        it["rating"] = t["rating"]
        it["preferredPosition"] = t["pos"]
        it["teamid"] = t["team"]
        it["nation"] = t["nation"]
        it["leagueId"] = t["league"]
        it["attributeList"] = [{"index": i, "value": v} for i, v in enumerate(t["attrs"])]
    drop = {d.get("id") for d in drop_dead}
    p["items"] = [i for i in items if i.get("id") not in drop]
    STORE._save()

    q = STORE.load()
    print("club: %d -> %d   coins=%s   purchased=%d"
          % (len(items), len(q.get("items", [])), q.get("coins"),
             len(q.get("purchased", []))))
    return 0


if __name__ == "__main__":
    sys.exit(main())
