#!/usr/bin/env python3
"""
mo_config.py — MoFin 统一配置管理（单例模式）

替代 MoFin 中散落在各文件的硬编码路径和常量。

⚠️ 铁律：所有 MoFin 模块必须从此处获取路径和配置，严禁硬编码。
  之前：DATA_DIR = "/home/hmo/web-dashboard/data"  (散落在 10+ 文件中)
  现在：from mo_config import config; config.data_dir

用法：
  from mo_config import config
  from mo_data import read_portfolio; data = read_portfolio()
"""

import os
import json
from pathlib import Path
from dataclasses import dataclass, field
from typing import List


@dataclass
class MoConfig:
    """MoFin 全局配置单例"""
    
    # ── 路径 ──────────────────────────────────────────────────────
    # 项目根目录
    project_dir: Path = field(default_factory=lambda: Path(__file__).parent.resolve())
    
    # 数据目录（mofin.db 等，所有数据只从 DB 读写）
    data_dir: Path = field(default_factory=lambda: Path(
        os.environ.get("MOFIN_DATA_DIR", "/home/hmo/web-dashboard/data")
    ))
    
    # SQLite 数据库路径
    db_path: Path = field(default=None)
    
    # 缓存目录
    cache_dir: Path = field(default_factory=lambda: Path.home() / ".cache" / "mofin")
    
    # Hermes 状态目录
    hermes_dir: Path = field(default_factory=lambda: Path.home() / ".hermes")
    
    # ── 关键数据文件路径（已废弃，仅保留为检查逻辑。新代码勿用） ──────

    @property
    def portfolio_path(self) -> Path:
        """⚠️ DEPRECATED: 数据已迁至 mofin.db holdings + portfolio_summary 表。"""
        import warnings
        warnings.warn("portfolio_path is deprecated — use mo_data.read_portfolio() for DB data", DeprecationWarning, stacklevel=2)
        return Path()

    @property
    def decisions_path(self) -> Path:
        """⚠️ DEPRECATED: 数据已迁至 mofin.db holding_strategies 表。"""
        import warnings
        warnings.warn("decisions_path is deprecated — use mo_data.read_decisions() for DB data", DeprecationWarning, stacklevel=2)
        return Path()

    @property
    def watchlist_path(self) -> Path:
        """⚠️ DEPRECATED: 数据已迁至 mofin.db watchlist_stocks 表。"""
        import warnings
        warnings.warn("watchlist_path is deprecated — use mo_data.read_watchlist() for DB data", DeprecationWarning, stacklevel=2)
        return Path()

    @property
    def price_events_path(self) -> Path:
        """⚠️ 已废弃！数据在 mofin.db price_events 表。"""
        return self.data_dir / "price_events.json"
    
    @property
    def live_prices_path(self) -> Path:
        """⚠️ DEPRECATED: 实时价格已迁移到 mofin_db.live_prices 表。"""
        return self.data_dir / "live_prices.json"
    
    @property
    def evaluation_input_path(self) -> Path:
        return self.data_dir / "evaluation_input.json"
    
    @property
    def multi_tf_cache_path(self) -> Path:
        """⚠️ DEPRECATED: 多周期缓存已迁移到 mofin_db.mtf_cache 表。"""
        return self.data_dir / "multi_tf_cache.json"
    
    @property
    def price_history_path(self) -> Path:
        return self.data_dir / "price_history.json"
    
    # ── DB 路径（懒加载） ────────────────────────────────────────
    
    def _get_db_path(self) -> Path:
        if self.db_path is None:
            self.db_path = self.data_dir / "mofin.db"
        return self.db_path
    
    # ── 汇率 ──────────────────────────────────────────────────────
    
    hk_rate_fallback: float = 0.87  # 港币→人民币 fallback 汇率
    
    # ── 小果 LLM 端点（用机器名，/etc/hosts 自动解析 LAN/EasyTier）─
    # node122 = 192.168.1.122 (LAN) / 10.144.144.2 (EasyTier)
    xiaoguo_host: str = "node122"
    xiaoguo_port: int = 18003
    
    @property
    def xiaoguo_url(self) -> str:
        return f"http://{self.xiaoguo_host}:{self.xiaoguo_port}"
    
    @property
    def xiaoguo_api_url(self) -> str:
        return f"{self.xiaoguo_url}/v1/chat/completions"
    
    port: int = field(default_factory=lambda: int(os.environ.get("PORT", "8899")))
    
    tdx_relay_url: str = field(
        default_factory=lambda: os.environ.get("TDX_RELAY_URL", "http://localhost:8080")
    )
    
    xmpp_agent_host: str = field(
        default_factory=lambda: os.environ.get("XMPP_AGENT_HOST", "localhost")
    )
    
    xmpp_agent_port: int = field(
        default_factory=lambda: int(os.environ.get("XMPP_AGENT_PORT", "5801"))
    )
    
    # ── DSA 集成 ──────────────────────────────────────────────────
    
    dsa_enabled: bool = field(
        default_factory=lambda: os.environ.get("DSA_ENABLED", "false").lower() == "true"
    )
    
    dsa_base_dir: Path = field(default_factory=lambda: Path(
        os.path.normpath(os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "..", "daily-stock-analysis",
            "ZhuLinsen-daily_stock_analysis-a448886"
        ))
    ))
    
    # ── 数据新鲜度 ────────────────────────────────────────────────
    
    market_hours_max_stale_min: int = 5   # 盘中最大过期时间（分钟）
    off_hours_max_stale_min: int = 120    # 盘后最大过期时间（分钟）
    
    # ── 验证 ──────────────────────────────────────────────────────
    
    def validate(self) -> List[str]:
        """验证配置，返回问题列表"""
        issues = []
        
        if not self.data_dir.exists():
            issues.append(f"数据目录不存在: {self.data_dir}")
        
        if not self.portfolio_path.exists():
            issues.append(f"portfolio_path 不存在（已废弃）: {self.portfolio_path}")

        if not self.decisions_path.exists():
            issues.append(f"decisions_path 不存在（已废弃）: {self.decisions_path}")
        
        return issues
    
    def ensure_dirs(self):
        """确保必要的目录存在"""
        self.data_dir.mkdir(parents=True, exist_ok=True)
        self.cache_dir.mkdir(parents=True, exist_ok=True)
        self.hermes_dir.mkdir(parents=True, exist_ok=True)
    
    # ── 输出 ──────────────────────────────────────────────────────
    
    def summary(self) -> str:
        """打印配置摘要"""
        lines = [
            "=== MoFin 配置 ===",
            f"项目目录: {self.project_dir}",
            f"数据目录: {self.data_dir} (存在: {self.data_dir.exists()})",
            f"DB路径: {self._get_db_path()} (存在: {self._get_db_path().exists()})",
            f"端口: {self.port}",
            f"TDX Relay: {self.tdx_relay_url}",
            f"DSA 集成: {'启用' if self.dsa_enabled else '关闭'}",
            f"港币汇率 fallback: {self.hk_rate_fallback}",
        ]
        issues = self.validate()
        if issues:
            lines.append(f"\n⚠️ 配置问题 ({len(issues)}):")
            for i in issues:
                lines.append(f"  - {i}")
        return "\n".join(lines)


# ── 单例 ────────────────────────────────────────────────────────────

_config_instance: MoConfig | None = None


def get_config() -> MoConfig:
    """获取全局配置单例"""
    global _config_instance
    if _config_instance is None:
        _config_instance = MoConfig()
    return _config_instance


# 便捷别名
config = property(lambda self: get_config())


# ── 模块级便捷访问 ──────────────────────────────────────────────────

def data_dir() -> Path:
    return get_config().data_dir

def ensure_dirs():
    get_config().ensure_dirs()


# ── 向后兼容：导出已废弃的路由常量 ──────────────────────────────────
# PORTFOLIO_PATH / DECISIONS_PATH / WATCHLIST_PATH 均已废弃（数据在 DB）。

def _lazy(attr):
    """懒加载属性，首次访问时从 config 获取"""
    return getattr(get_config(), attr)

# 为兼容旧代码导出以下变量
PORTFOLIO_PATH = None   # 改用 config.portfolio_path
DECISIONS_PATH = None    # 改用 config.decisions_path
WATCHLIST_PATH = None    # 改用 config.watchlist_path


# ── 自检 ────────────────────────────────────────────────────────────

if __name__ == "__main__":
    cfg = get_config()
    print(cfg.summary())
