"""
股票实时行情查询

用法: python stock_quote.py <stock_code> [--detail]
  stock_code: 6位A股代码(如 600519) 或 5位港股代码(如 03888)
  --detail:   获取详细信息（公司概况等）

AKShare接口:
  A股主: ak.stock_zh_a_spot() — 新浪实时行情（稳定可用）
  A股备: ak.stock_zh_a_spot_em() — 东方财富实时行情（含PE/PB/市值等）
  A股补: ak.stock_individual_info_em(symbol) — 个股详细信息(行业/市值)
  港股主: ak.stock_hk_hist_min_em(symbol) — 东方财富分钟线（实时，盘中最快）
  港股备: ak.stock_hk_daily(symbol) — 新浪港股日线行情（T-1数据，稳定）
  港股补: ak.stock_hk_financial_indicator_em(symbol) — PE/PB/市值/ROE
  港股补: ak.stock_hk_company_profile_em(symbol) — 公司名称/行业
"""

import sys
import argparse
from datetime import datetime

sys.path.insert(0, '.')
from _utils import normalize_code, get_market_prefix, output_json, output_error, check_akshare, safe_float, is_hk_code


def _fetch_em(code):
    """东方财富A股接口：数据最全（含PE/PB/市值/换手率/量比等）"""
    import akshare as ak

    df = ak.stock_zh_a_spot_em()
    row = df[df['代码'] == code]

    if row.empty:
        return None

    r = row.iloc[0]
    return {
        "code": code,
        "name": str(r.get('名称', '')),
        "price": safe_float(r.get('最新价')),
        "change_pct": safe_float(r.get('涨跌幅')),
        "change_amt": safe_float(r.get('涨跌额')),
        "volume": safe_float(r.get('成交量')),
        "amount": safe_float(r.get('成交额')),
        "amplitude": safe_float(r.get('振幅')),
        "high": safe_float(r.get('最高')),
        "low": safe_float(r.get('最低')),
        "open": safe_float(r.get('今开')),
        "prev_close": safe_float(r.get('昨收')),
        "turnover_rate": safe_float(r.get('换手率')),
        "pe_ratio": safe_float(r.get('市盈率-动态')),
        "pb_ratio": safe_float(r.get('市净率')),
        "total_market_cap": safe_float(r.get('总市值')),
        "circulating_market_cap": safe_float(r.get('流通市值')),
        "rise_speed": safe_float(r.get('5分钟涨速')),
        "volume_ratio": safe_float(r.get('量比')),
        "data_source": "eastmoney",
        "data_time": datetime.now().strftime('%Y-%m-%d %H:%M'),
    }


def _fetch_sina(code):
    """新浪A股日线接口：快速稳定（当日数据可用）"""
    import akshare as ak

    prefix = get_market_prefix(code)
    sina_code = f"{prefix}{code}"

    # 优先用 daily 获取当日数据（快速）
    try:
        df = ak.stock_zh_a_daily(symbol=sina_code, adjust="qfq")
        if not df.empty and len(df) >= 2:
            r = df.iloc[-1]
            prev_r = df.iloc[-2]
            prev_close = safe_float(prev_r['close'])
            price = safe_float(r['close'])
            change_amt = round(price - prev_close, 3) if prev_close and price else None
            change_pct = round(change_amt / prev_close * 100, 3) if prev_close and change_amt is not None else None
            return {
                "code": code,
                "name": "",
                "price": price,
                "change_pct": change_pct,
                "change_amt": change_amt,
                "volume": safe_float(r.get('volume')),
                "amount": safe_float(r.get('amount')),
                "high": safe_float(r.get('high')),
                "low": safe_float(r.get('low')),
                "open": safe_float(r.get('open')),
                "prev_close": prev_close,
                "date": str(r.get('date', '')),
                "data_source": "sina_daily",
                "data_time": str(r.get('date', '')) + " (收盘)",
            }
    except Exception:
        pass

    # 备选：全量spot接口（慢，但含名称）
    df = ak.stock_zh_a_spot()
    row = df[df['代码'] == sina_code]

    if row.empty:
        return None

    r = row.iloc[0]
    return {
        "code": code,
        "name": str(r.get('名称', '')),
        "price": safe_float(r.get('最新价')),
        "change_pct": safe_float(r.get('涨跌幅')),
        "change_amt": safe_float(r.get('涨跌额')),
        "volume": safe_float(r.get('成交量')),
        "amount": safe_float(r.get('成交额')),
        "high": safe_float(r.get('最高')),
        "low": safe_float(r.get('最低')),
        "open": safe_float(r.get('今开')),
        "prev_close": safe_float(r.get('昨收')),
        "data_source": "sina",
        "data_time": datetime.now().strftime('%Y-%m-%d %H:%M'),
    }


def _fetch_hk_realtime(code):
    """东方财富港股分钟线接口：盘中实时数据（优先使用）"""
    import akshare as ak

    try:
        df = ak.stock_hk_hist_min_em(symbol=code, period='1')
        if df.empty:
            return None

        last = df.iloc[-1]
        price = safe_float(last.get('收盘'))

        # 从分钟线构造今日行情
        today_str = str(last.get('时间', ''))[:10]
        today_data = df[df['时间'].astype(str).str.startswith(today_str)]

        if today_data.empty:
            return None

        open_price = safe_float(today_data.iloc[0].get('开盘'))
        high = max(safe_float(r.get('最高')) for _, r in today_data.iterrows() if safe_float(r.get('最高')) is not None)
        low = min(safe_float(r.get('最低')) for _, r in today_data.iterrows() if safe_float(r.get('最低')) is not None)
        volume = sum(safe_float(r.get('成交量')) or 0 for _, r in today_data.iterrows())
        amount = sum(safe_float(r.get('成交额')) or 0 for _, r in today_data.iterrows())

        # 计算涨跌需要昨日收盘
        prev_close = None
        change_pct = None
        change_amt = None
        try:
            daily_df = ak.stock_hk_daily(symbol=code, adjust="qfq")
            if len(daily_df) >= 2:
                prev_close = safe_float(daily_df.iloc[-2]['close'])
                if prev_close and price:
                    change_amt = round(price - prev_close, 3)
                    change_pct = round(change_amt / prev_close * 100, 3)
        except Exception:
            pass

        return {
            "code": code,
            "name": "",
            "price": price,
            "change_pct": change_pct,
            "change_amt": change_amt,
            "volume": volume,
            "amount": amount,
            "high": high,
            "low": low,
            "open": open_price,
            "prev_close": prev_close,
            "date": today_str,
            "data_source": "eastmoney_min",
            "data_time": str(last.get('时间', '')),
        }
    except Exception:
        return None


def _fetch_hk_sina(code):
    """新浪港股接口：通过 stock_hk_daily 取最新数据（T-1，稳定）"""
    import akshare as ak

    df = ak.stock_hk_daily(symbol=code, adjust="qfq")
    if df.empty:
        return None

    r = df.iloc[-1]
    prev_r = df.iloc[-2] if len(df) >= 2 else None
    prev_close = safe_float(prev_r['close']) if prev_r is not None else None
    price = safe_float(r['close'])
    change_amt = round(price - prev_close, 3) if prev_close and price else None
    change_pct = round(change_amt / prev_close * 100, 3) if prev_close and change_amt is not None else None

    return {
        "code": code,
        "name": "",
        "price": price,
        "change_pct": change_pct,
        "change_amt": change_amt,
        "volume": safe_float(r.get('volume')),
        "amount": safe_float(r.get('amount')),
        "high": safe_float(r.get('high')),
        "low": safe_float(r.get('low')),
        "open": safe_float(r.get('open')),
        "prev_close": prev_close,
        "date": str(r.get('date', '')),
        "data_source": "sina_hk",
        "data_time": str(r.get('date', '')) + " (收盘)",
    }


def _fetch_hk_em(code):
    """东方财富港股接口（含名称、振幅、换手率等更多字段）"""
    import akshare as ak

    df = ak.stock_hk_spot_em()
    row = df[df['代码'] == code]

    if row.empty:
        return None

    r = row.iloc[0]
    return {
        "code": code,
        "name": str(r.get('名称', '')),
        "price": safe_float(r.get('最新价')),
        "change_pct": safe_float(r.get('涨跌幅')),
        "change_amt": safe_float(r.get('涨跌额')),
        "volume": safe_float(r.get('成交量')),
        "amount": safe_float(r.get('成交额')),
        "high": safe_float(r.get('最高')),
        "low": safe_float(r.get('最低')),
        "open": safe_float(r.get('今开')),
        "prev_close": safe_float(r.get('昨收')),
        "amplitude": safe_float(r.get('振幅')),
        "turnover_rate": safe_float(r.get('换手率')),
        "data_source": "eastmoney_hk",
        "data_time": datetime.now().strftime('%Y-%m-%d %H:%M'),
    }


def _enrich_hk(data, code):
    """补充港股额外字段：PE/PB/市值/ROE/行业/名称"""
    import akshare as ak

    # 补充财务指标（PE/PB/市值/ROE等）
    try:
        fi = ak.stock_hk_financial_indicator_em(symbol=code)
        if not fi.empty:
            r = fi.iloc[0]
            data.setdefault("pe_ratio", safe_float(r.get('市盈率')))
            data.setdefault("pb_ratio", safe_float(r.get('市净率')))
            data.setdefault("total_market_cap", safe_float(r.get('总市值(港元)')))
            data["roe"] = safe_float(r.get('股东权益回报率(%)'))
            data["net_profit"] = safe_float(r.get('净利润'))
            data["net_profit_growth"] = safe_float(r.get('净利润滚动环比增长(%)'))
            data["revenue"] = safe_float(r.get('营业总收入'))
            data["revenue_growth"] = safe_float(r.get('营业总收入滚动环比增长(%)'))
            data["net_margin"] = safe_float(r.get('销售净利率(%)'))
            data["eps"] = safe_float(r.get('基本每股收益(元)'))
            data["dividend_yield"] = safe_float(r.get('股息率TTM(%)'))
        else:
            data["financial_indicator_error"] = "东方财富港股指标接口返回空数据"
    except Exception as e:
        data["financial_indicator_error"] = f"获取财务指标失败: {str(e)}"

    # 补充公司名称和行业
    if not data.get("name") or not data.get("industry"):
        try:
            profile = ak.stock_hk_company_profile_em(symbol=code)
            if not profile.empty:
                p = profile.iloc[0]
                if not data.get("name"):
                    data["name"] = str(p.get('公司名称', ''))
                data["industry"] = str(p.get('所属行业', ''))
                data["chairman"] = str(p.get('董事长', ''))
        except Exception:
            pass


def main():
    parser = argparse.ArgumentParser(description='股票实时行情查询')
    parser.add_argument('stock_code', help='股票代码，如 600519(A股) 或 03888(港股)')
    parser.add_argument('--detail', action='store_true', help='获取详细信息')
    args = parser.parse_args()

    # 检测AKShare
    err = check_akshare()
    if err:
        output_error(err)
        return

    code = normalize_code(args.stock_code)

    try:
        import akshare as ak

        # 港股：优先分钟线实时 → 新浪daily(T-1) → 东方财富spot → 补充丰富字段
        if is_hk_code(code):
            data = None

            # 1. 优先：东方财富分钟线（盘中实时）
            try:
                data = _fetch_hk_realtime(code)
            except Exception:
                pass

            # 2. 备选：新浪日线（T-1，稳定）
            if data is None:
                try:
                    data = _fetch_hk_sina(code)
                except Exception:
                    pass

            # 3. 兜底：东方财富港股spot
            if data is None:
                try:
                    data = _fetch_hk_em(code)
                except Exception as e:
                    output_error(f"获取港股行情失败: {str(e)}")
                    return

            if data is None:
                output_error(f"未找到港股代码: {code}，请确认代码正确(5位数字如 03888)")
                return

            # 补充PE/PB/市值/ROE/行业/名称
            _enrich_hk(data, code)

            # 时效性检查：标注数据是否过时
            from datetime import date
            today = date.today()
            data_date_str = data.get('date', '') or data.get('data_time', '')[:10]
            if data_date_str:
                try:
                    data_date = date.fromisoformat(data_date_str[:10])
                    days_old = (today - data_date).days
                    if days_old > 0:
                        data["data_staleness"] = f"数据为{days_old}天前({data_date_str})"
                        if data.get("data_source", "").endswith("_daily") or data.get("data_source") == "sina_hk":
                            data["data_staleness"] += "，日线接口为T-1数据（最近交易日收盘）"
                        elif days_old > 3:
                            data["data_staleness"] += "，数据可能过时，请确认是否为非交易日"
                except (ValueError, TypeError):
                    pass

            # 可选：公司详细信息
            if args.detail:
                try:
                    profile = ak.stock_hk_company_profile_em(symbol=code)
                    if not profile.empty:
                        data["detail"] = {col: str(profile.iloc[0][col]) for col in profile.columns}
                except Exception:
                    data["detail"] = None

            output_json(data)
            return

        # A股：优先新浪（稳定），失败回退东方财富
        data = None
        try:
            data = _fetch_sina(code)
        except Exception:
            pass

        if data is None:
            try:
                data = _fetch_em(code)
            except Exception as e2:
                output_error(f"获取行情失败: {str(e2)}")
                return

        if data is None:
            output_error(f"未找到股票代码: {code}")
            return

        # 非东方财富数据源时，尝试补充个股信息
        if data.get("data_source") != "eastmoney":
            try:
                info_df = ak.stock_individual_info_em(symbol=code)
                for _, row_info in info_df.iterrows():
                    key = str(row_info.iloc[0])
                    val = str(row_info.iloc[1])
                    if key == '总市值':
                        data["total_market_cap"] = safe_float(val)
                    elif key == '流通市值':
                        data["circulating_market_cap"] = safe_float(val)
                    elif key == '行业':
                        data["industry"] = val
            except Exception:
                pass

        # 可选：获取详细信息
        if args.detail:
            try:
                info_df = ak.stock_individual_info_em(symbol=code)
                detail = {}
                for _, row_info in info_df.iterrows():
                    item_key = str(row_info.iloc[0])
                    item_val = str(row_info.iloc[1])
                    detail[item_key] = item_val
                data["detail"] = detail
            except Exception:
                data["detail"] = None

        # A股时效性检查
        from datetime import date as date_cls
        today = date_cls.today()
        data_date_str = data.get('date', '') or data.get('data_time', '')[:10]
        if data_date_str:
            try:
                data_date = date_cls.fromisoformat(data_date_str[:10])
                days_old = (today - data_date).days
                if days_old > 0:
                    data["data_staleness"] = f"数据为{days_old}天前({data_date_str})"
                    if data.get("data_source") in ("sina_daily", "sina"):
                        data["data_staleness"] += "，日线接口为T-1数据（最近交易日收盘）"
                    elif days_old > 3:
                        data["data_staleness"] += "，数据可能过时，请确认是否为非交易日"
            except (ValueError, TypeError):
                pass

        output_json(data)

    except Exception as e:
        output_error(f"获取行情失败: {str(e)}")


if __name__ == '__main__':
    main()
