"""
统一数据源模块 — djapi/api/stock/ 的单一数据入口。

归一化 Tushare / AkShare / MySQL 三种数据源。
所有模块通过此入口获取数据连接，不再各自创建 pro 实例。

用法:
    from .data_source import get_tushare_pro, get_mysql_db

    pro = get_tushare_pro()
    df = pro.daily(ts_code='000001.SZ', ...)

    db = get_mysql_db()
    rows = db.query("SELECT * FROM xwlb_daily WHERE ...")

扩展新数据源:
    class NewSource: ...
    _sources['new'] = NewSource()
    def get_new_source(): return _sources['new']
"""

import os
import threading

import tushare as ts

# 延迟加载 AkShare（避免不必要的导入开销）
_akshare = None


def _get_akshare():
    global _akshare
    if _akshare is None:
        import akshare as ak
        _akshare = ak
    return _akshare


# ═══════════════════════════════════════════════════════════
# Token 加载
# ═══════════════════════════════════════════════════════════

def get_ts_token() -> str:
    """获取 Tushare Token，优先级：环境变量 TUSHARE_TS_TOKEN > TUSHARE_TOKEN > config.py"""
    token = os.getenv("TUSHARE_TS_TOKEN", "") or os.getenv("TUSHARE_TOKEN", "")
    if not token:
        try:
            from .config import TS_TOKEN
            token = TS_TOKEN
        except ImportError:
            try:
                from config import TS_TOKEN
                token = TS_TOKEN
            except ImportError:
                pass
    return token


# ═══════════════════════════════════════════════════════════
# Tushare Pro 连接池（线程安全单例）
# ═══════════════════════════════════════════════════════════

_pro_lock = threading.Lock()
_pro = None


def get_tushare_pro():
    """获取 Tushare pro_api 实例（全局单例，线程安全）。"""
    global _pro
    if _pro is not None:
        return _pro
    with _pro_lock:
        if _pro is not None:
            return _pro
        token = get_ts_token()
        ts.set_token(token)
        _pro = ts.pro_api()
    return _pro


def reset_tushare_pro():
    """重置 Tushare 连接（token 变更时调用）。"""
    global _pro
    with _pro_lock:
        _pro = None


# ═══════════════════════════════════════════════════════════
# MySQL 连接
# ═══════════════════════════════════════════════════════════

_mysql_db = None


def get_mysql_db():
    """获取 MySQLDB 实例（全局单例）。"""
    global _mysql_db
    if _mysql_db is not None:
        return _mysql_db
    try:
        from ..utils.mysql_handler import MySQLDB
    except (ImportError, ValueError):
        try:
            from utils.mysql_handler import MySQLDB
        except ImportError:
            return None
    _mysql_db = MySQLDB()
    return _mysql_db


# ═══════════════════════════════════════════════════════════
# 日线行情 — 双源 fallback（Tushare → AkShare）
# ═══════════════════════════════════════════════════════════

def get_daily(ts_code: str, start_date: str, end_date: str, source: str = "tushare"):
    """
    获取个股日线行情。

    参数:
        ts_code: 如 '000001.SZ'
        start_date: YYYYMMDD
        end_date: YYYYMMDD
        source: 'tushare' | 'akshare' | 'auto' (tushare优先)

    返回:
        pd.DataFrame (trade_date, open, high, low, close, vol, amount, ...)
    """
    import pandas as pd

    if source == "auto":
        # Tushare 优先
        try:
            df = get_daily(ts_code, start_date, end_date, source="tushare")
            if df is not None and not df.empty:
                return df
        except Exception:
            pass
        return get_daily(ts_code, start_date, end_date, source="akshare")

    if source == "tushare":
        pro = get_tushare_pro()
        df = pro.daily(
            ts_code=ts_code, start_date=start_date, end_date=end_date,
            fields="ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount"
        )
        if df is not None and not df.empty:
            df["trade_date"] = df["trade_date"].astype(str)
        return df

    if source == "akshare":
        symbol = ts_code.replace(".SZ", "").replace(".SH", "").replace(".BJ", "")
        ak = _get_akshare()
        df = ak.stock_zh_a_hist(
            symbol=symbol, period="daily",
            start_date=start_date, end_date=end_date, adjust="qfq"
        )
        if df is not None and not df.empty:
            df = df.rename(columns={
                "日期": "trade_date", "开盘": "open", "收盘": "close",
                "最高": "high", "最低": "low", "成交量": "vol", "成交额": "amount",
                "涨跌幅": "pct_chg", "涨跌额": "change",
            })
            df["ts_code"] = ts_code
            df["trade_date"] = df["trade_date"].astype(str)
        return df if df is not None else pd.DataFrame()

    raise ValueError("Unknown source: {}".format(source))


# ═══════════════════════════════════════════════════════════
# 扩展点：未来新增数据源
# ═══════════════════════════════════════════════════════════
#
# 1. 在 _sources dict 中注册新源
# 2. 实现与 get_daily() 相同签名的函数
# 3. 在 get_daily(source=...) 中添加路由
#
# _sources = {
#     "tushare": TushareDailySource(),
#     "akshare": AkShareDailySource(),
#     "wind": WindDailySource(),       # 未来
#     "joinquant": JoinQuantSource(),  # 未来
# }
