#!/usr/bin/env python3
"""data_flow_audit.py — 数据流架构审计

对比实际读写关系 vs 设计意图（预期读写方），标记违规。
输出给 mofin_health.py 消费，在 Dashboard 数据流 Tab 显示。
"""
import re, os, json, subprocess
from pathlib import Path

PROFILE_SCRIPTS = Path("/home/hmo/.hermes/profiles/position-analyst/scripts")
MOFIN_SCRIPTS = Path("/home/hmo/MoFin/scripts")
SCRIPTS_DIR = PROFILE_SCRIPTS if PROFILE_SCRIPTS.exists() else MOFIN_SCRIPTS

# ── 设计意图注册表 ──
# 每张核心表的预期写入方（谁应该写）+ 预期用途
DESIGN_INTENT = {
    "live_prices": {
        "expected_writers": ["price_monitor"],
        "policy": "single_writer",
        "desc": "实时价格缓存 — 仅price_monitor写入，其他一律读",
        "remarks": "违规: 自行拉API会导致并发写+重复请求"
    },
    "holdings": {
        "expected_writers": ["import_holding_xls", "dad_asset_update"],
        "policy": "restricted",
        "desc": "持仓数据 — 仅通过成交截图导入或Dad确认更新",
        "remarks": ""
    },
    "portfolio_summary": {
        "expected_writers": ["import_holding_xls", "dad_asset_update", "price_monitor"],
        "policy": "restricted",
        "desc": "组合汇总 — 持仓导入+价格更新",
        "remarks": ""
    },
    "cash_log": {
        "expected_writers": ["import_holding_xls", "dad_asset_update"],
        "policy": "restricted",
        "desc": "资金流水 — 仅截图导入或Dad确认",
        "remarks": ""
    },
    "holding_strategies": {
        "expected_writers": ["strategy_review", "strategy_evaluator", "per_stock_reassess"],
        "policy": "multi_writer",
        "desc": "策略数据 — 多个分析流程可写",
        "remarks": ""
    },
    "price_events": {
        "expected_writers": ["price_monitor"],
        "policy": "single_writer",
        "desc": "价格触发事件 — 仅price_monitor写入",
        "remarks": ""
    },
    "sector_snapshots": {
        "expected_writers": ["market_watch"],
        "policy": "single_writer",
        "desc": "板块快照 — 仅market_watch写入",
        "remarks": ""
    },
}

# 直接拉API的价格违规扫描
API_PATTERNS = [
    r"qt\.gtimg\.cn",
    r"tencent.*quote",
    r"get_quote",
    r"fetch.*price",
    r"stock_quote\.",
]

def scan_price_violations():
    """扫描不走live_prices直接拉API的脚本"""
    violations = []
    for py_file in sorted(SCRIPTS_DIR.glob("*.py")):
        name = py_file.stem
        if name in ("price_monitor", "stock_quote", "mofin_db", "mo_data", "deploy_sync"):
            continue  # 这些是基础设施/被允许的
        content = py_file.read_text()
        for pat in API_PATTERNS:
            if re.search(pat, content):
                # 找具体行号
                lines = content.split("\n")
                for i, line in enumerate(lines, 1):
                    if re.search(pat, line):
                        violations.append({
                            "script": name,
                            "line": i,
                            "code": line.strip()[:80],
                        })
                        break
    return violations


def audit():
    """读取当前数据流扫描结果，叠加设计意图"""
    from mo_data import get_flow
    # 这里应该读mofin_health输出的entities
    
    violations = scan_price_violations()
    
    result = {
        "design_intent": DESIGN_INTENT,
        "price_api_violations": violations,
        "summary": {
            "total_violations": len(violations),
            "violating_scripts": list(set(v["script"] for v in violations)),
        }
    }
    
    return result


if __name__ == "__main__":
    import json
    result = audit()
    print(json.dumps(result, ensure_ascii=False, indent=2))
