"""清空指定用户的签到记录,方便反复测试"未签到→自动弹窗→签到领金币"。

默认**只删 signin_record**(签到历史),不动金币/现金——这样能保留你已注入/兑换的余额,
只把"今天是否已签到 / 连续天数"重置掉。删后当天即变成"未签到",再进福利页会重新自动弹签到弹窗。

⚠️ 注意:只删签到记录的话,之前签到已发的金币仍留在余额和 coin_transaction 里(biz_type='signin')。
如果想把签到发的金币也一并退掉(余额减回、删 signin 流水),加 --with-coins。

用法(在 shaguabijia-app-server 目录下,用本项目的 python 跑):
    python scripts/reset_signin.py              # 只清 user_id=2 的签到记录
    python scripts/reset_signin.py 5            # 清 user_id=5
    python scripts/reset_signin.py --all        # 清所有用户的签到记录
    python scripts/reset_signin.py --with-coins # 连签到发的金币一起退回(余额减、删 signin 流水)
    python scripts/reset_signin.py --dry-run    # 只看现状,不改

DB 默认取 <项目根>/data/app.db,可用 --db 指定。
"""
from __future__ import annotations

import argparse
import sqlite3
import sys
from pathlib import Path

# Windows 控制台默认 GBK,强制 UTF-8 否则中文输出乱码
if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8")

# 本脚本在 scripts/ 下,项目根是上一级
DEFAULT_DB = Path(__file__).resolve().parent.parent / "data" / "app.db"


def snapshot(cur: sqlite3.Cursor, where: str, params: tuple) -> dict:
    """返回签到记录数 + 签到金币流水数/总额 + 账户金币余额,用于打印 before/after。"""
    signin_rows = cur.execute(
        f"select count(*) from signin_record where {where}", params
    ).fetchone()[0]
    signin_coin_rows, signin_coin_sum = cur.execute(
        f"select count(*), coalesce(sum(amount), 0) from coin_transaction "
        f"where biz_type='signin' and {where}",
        params,
    ).fetchone()
    accounts = cur.execute(
        f"select user_id, coin_balance, total_coin_earned from coin_account where {where}",
        params,
    ).fetchall()
    return {
        "signin_rows": signin_rows,
        "signin_coin_rows": signin_coin_rows,
        "signin_coin_sum": signin_coin_sum,
        "accounts": accounts,
    }


def print_snapshot(label: str, snap: dict) -> None:
    print(f"--- {label} ---")
    print(f"  signin_record: {snap['signin_rows']}")
    print(f"  coin_transaction(signin): {snap['signin_coin_rows']} 条, 共 {snap['signin_coin_sum']} 金币")
    if snap["accounts"]:
        for uid, coin, earned in snap["accounts"]:
            print(f"  coin_account user={uid}: coin={coin} earned={earned}")
    else:
        print("  coin_account: (无)")


def main() -> None:
    parser = argparse.ArgumentParser(description="清空用户签到记录")
    parser.add_argument("user_id", nargs="?", type=int, default=2,
                        help="要清的 user_id(默认 2)")
    parser.add_argument("--all", action="store_true", help="清所有用户")
    parser.add_argument("--with-coins", action="store_true",
                        help="同时退回签到发的金币(余额减、删 signin 流水)")
    parser.add_argument("--dry-run", action="store_true", help="只看现状,不修改")
    parser.add_argument("--db", default=str(DEFAULT_DB), help="SQLite 路径")
    args = parser.parse_args()

    if args.all:
        where, params, scope = "1=1", (), "ALL users"
    else:
        where, params, scope = "user_id=?", (args.user_id,), f"user_id={args.user_id}"

    db_path = Path(args.db)
    if not db_path.exists():
        raise SystemExit(f"DB 不存在: {db_path}")

    conn = sqlite3.connect(str(db_path))
    cur = conn.cursor()
    print(f"DB: {db_path}  scope: {scope}  with_coins: {args.with_coins}")
    print_snapshot("before", snapshot(cur, where, params))

    if args.dry_run:
        print("(dry-run,未修改)")
        conn.close()
        return

    if args.with_coins:
        # 先按用户把签到金币总额退回(余额、累计收益都减),再删 signin 流水
        rows = cur.execute(
            f"select user_id, coalesce(sum(amount), 0) from coin_transaction "
            f"where biz_type='signin' and {where} group by user_id",
            params,
        ).fetchall()
        for uid, total in rows:
            cur.execute(
                "update coin_account set coin_balance = coin_balance - ?, "
                "total_coin_earned = max(0, total_coin_earned - ?) where user_id = ?",
                (total, total, uid),
            )
        cur.execute(f"delete from coin_transaction where biz_type='signin' and {where}", params)

    cur.execute(f"delete from signin_record where {where}", params)
    conn.commit()

    print_snapshot("after", snapshot(cur, where, params))
    conn.close()
    print("签到记录已清空。提醒:App 内存里的状态不会自动同步,重启 App 或进收益明细页刷新;"
          "重进福利页(当天未签到)会重新自动弹签到弹窗。")


if __name__ == "__main__":
    main()
