#!/usr/bin/env python3
"""holdings_reconciliation.py — 每日持仓数据一致性校验

在 decisions.json 和 portfolio.json 之间做双向核对：
1. 股数不一致 → 以 portfolio.json 为准（券商导入为源头真理）
2. 股票存在一个文件但不存在另一个 → 同步到双方一致
3. 总资产重新计算并写入双方

24小时内禁止修改策略参数（止盈/止损/买入区），只修股数和总资产。
"""
import json, sys
from datetime import datetime

DECISIONS = "/home/hmo/web-dashboard/data/decisions.json"
PORTFOLIO = "/home/hmo/web-dashboard/data/portfolio.json"

def main():
    dec = json.load(open(DECISIONS))
    pf = json.load(open(PORTFOLIO))

    # Build maps
    dmap = {d["code"]: d for d in dec.get("decisions", [])}
    pmap = {h["code"]: h for h in pf.get("holdings", []) if h.get("shares", 0) > 0}

    changes = []

    # 1. Remove from decisions if not in portfolio (ghost holdings)
    for code in list(dmap.keys()):
        d = dmap[code]
        in_portfolio = code in pmap
        if not in_portfolio:
            if d.get("shares", 0) > 0:
                old = d["shares"]
                d["shares"] = 0
                d["type"] = "自选策略"
                d.setdefault("changelog", []).append({
                    "time": datetime.now().strftime("%Y-%m-%d %H:%M"),
                    "from": old,
                    "to": 0,
                    "reason": "reconciliation: 不在券商持仓"
                })
                changes.append(f"  {d.get('name','')}({code}): 清仓{old}→0股(不在portfolio)")
            continue
        # Same stock in both: sync share count (portfolio is source of truth)
        p_shares = pmap[code]["shares"]
        if d.get("shares", 0) != p_shares:
            old = d.get("shares", 0)
            d["shares"] = p_shares
            d["type"] = "持仓策略"
            d.setdefault("changelog", []).append({
                "time": datetime.now().strftime("%Y-%m-%d %H:%M"),
                "from": old,
                "to": p_shares,
                "reason": "reconciliation: 股数与券商一致"
            })
            changes.append(f"  {d.get('name','')}({code}): 股数{old}→{p_shares}(对齐portfolio)")

    # 2. Add to decisions if in portfolio but not in decisions
    for code in pmap:
        h = pmap[code]
        if code not in dmap:
            # Stock is in portfolio but not in decisions → add stub
            stub = {
                "code": code,
                "name": h.get("name", f"STOCK_{code}"),
                "shares": h["shares"],
                "price": h.get("price", 0),
                "stop_loss": 0,
                "take_profit": 0,
                "entry_low": 0,
                "entry_high": 0,
                "cost": h.get("cost", 0),
                "type": "持仓策略",
                "status": "active",
                "timing_signal": "持有",
                "action": "持仓策略 | 等待技术分析完善",
                "tech_snapshot": "",
                "action_note": "reconciliation: 自动补充",
                "reassessed_at": datetime.now().strftime("%Y-%m-%d %H:%M"),
                "updated_at": datetime.now().strftime("%Y-%m-%d %H:%M"),
                "changelog": [{
                    "time": datetime.now().strftime("%Y-%m-%d %H:%M"),
                    "reason": "reconciliation: 券商持仓→自动补充策略"
                }],
                "trigger": {},
                "analysis": {},
                "currency": "CNY"
            }
            dec["decisions"].append(stub)
            changes.append(f"  {stub['name']}({code}): decisions新增持仓({h['shares']}股,来自portfolio)")

    # 3. Recalculate total_assets in portfolio (use mo_models for unified formula)
    import sys, os
    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    from mo_models import calc_total_assets
    total_assets = calc_total_assets(pf)
    dec_total = 0
    for d in dec.get("decisions", []):
        if d.get("shares", 0) > 0 and d.get("price", 0) > 0:
            dec_total += d["shares"] * d["price"]

    old_total = pf.get("total_assets", 0)
    pf["total_assets"] = total_assets
    pf["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M")

    # 4. Report
    now = datetime.now().strftime("%Y-%m-%d %H:%M")
    print(f"【持仓一致性校验】{now}")
    print(f"")
    if changes:
        print(f"修正项 ({len(changes)}):")
        for c in changes:
            print(c)
    else:
        print("无差异，全部一致 ✅")
    print(f"")
    print(f"portfolio stock_value: {stock_value:.2f}")
    print(f"portfolio cash: {cash:.2f}")
    print(f"portfolio total_assets: {old_total} → {total_assets}")
    print(f"decisions stock_value: {dec_total:.2f}")
    print(f"decisions count(shares>0): {len([d for d in dec['decisions'] if d.get('shares',0)>0])}")

    # Write
    dec["total"] = len(dec["decisions"])
    json.dump(dec, open(DECISIONS, "w"), ensure_ascii=False, indent=2)
    json.dump(pf, open(PORTFOLIO, "w"), ensure_ascii=False, indent=2)
    print(f"done")

if __name__ == "__main__":
    main()
