#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
Date: 2025/11/10 15:30
Desc: 新浪财经-基金行情
https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
"""

import pandas as pd
import py_mini_racer
import requests

from akshare.stock.cons import hk_js_decode
from akshare.utils import demjson


def fund_etf_category_sina(symbol: str = "LOF基金") -> pd.DataFrame:
    """
    新浪财经-基金列表
    https://vip.stock.finance.sina.com.cn/fund_center/index.html#jjhqetf
    :param symbol: choice of {"封闭式基金", "ETF基金", "LOF基金"}
    :type symbol: str
    :return: 指定 symbol 的基金列表
    :rtype: pandas.DataFrame
    """
    fund_map = {
        "封闭式基金": "close_fund",
        "ETF基金": "etf_hq_fund",
        "LOF基金": "lof_hq_fund",
    }
    url = (
        "https://vip.stock.finance.sina.com.cn/quotes_service/api/jsonp.php/"
        "IO.XSRV2.CallbackList['da_yPT46_Ll7K6WD']/Market_Center.getHQNodeDataSimple"
    )
    params = {
        "page": "1",
        "num": "5000",
        "sort": "symbol",
        "asc": "0",
        "node": fund_map[symbol],
        "[object HTMLDivElement]": "qvvne",
    }
    r = requests.get(url, params=params)
    data_text = r.text
    data_json = demjson.decode(data_text[data_text.find("([") + 1 : -2])
    temp_df = pd.DataFrame(data_json)
    if symbol == "封闭式基金":
        temp_df.columns = [
            "代码",
            "名称",
            "最新价",
            "涨跌额",
            "涨跌幅",
            "买入",
            "卖出",
            "昨收",
            "今开",
            "最高",
            "最低",
            "成交量",
            "成交额",
            "_",
            "_",
        ]
    else:
        temp_df.columns = [
            "代码",
            "名称",
            "最新价",
            "涨跌额",
            "涨跌幅",
            "买入",
            "卖出",
            "昨收",
            "今开",
            "最高",
            "最低",
            "成交量",
            "成交额",
            "_",
            "_",
            "_",
            "_",
        ]
    temp_df = temp_df[
        [
            "代码",
            "名称",
            "最新价",
            "涨跌额",
            "涨跌幅",
            "买入",
            "卖出",
            "昨收",
            "今开",
            "最高",
            "最低",
            "成交量",
            "成交额",
        ]
    ]
    temp_df["最新价"] = pd.to_numeric(temp_df["最新价"], errors="coerce")
    temp_df["涨跌额"] = pd.to_numeric(temp_df["涨跌额"], errors="coerce")
    temp_df["涨跌幅"] = pd.to_numeric(temp_df["涨跌幅"], errors="coerce")
    temp_df["买入"] = pd.to_numeric(temp_df["买入"], errors="coerce")
    temp_df["卖出"] = pd.to_numeric(temp_df["卖出"], errors="coerce")
    temp_df["昨收"] = pd.to_numeric(temp_df["昨收"], errors="coerce")
    temp_df["今开"] = pd.to_numeric(temp_df["今开"], errors="coerce")
    temp_df["最高"] = pd.to_numeric(temp_df["最高"], errors="coerce")
    temp_df["最低"] = pd.to_numeric(temp_df["最低"], errors="coerce")
    temp_df["成交量"] = pd.to_numeric(temp_df["成交量"], errors="coerce")
    temp_df["成交额"] = pd.to_numeric(temp_df["成交额"], errors="coerce")
    return temp_df


def fund_etf_hist_sina(symbol: str = "sh510050") -> pd.DataFrame:
    """
    新浪财经-基金-ETF 基金-日行情数据
    https://finance.sina.com.cn/fund/quotes/159996/bc.shtml
    :param symbol: 基金名称, 可以通过 ak.fund_etf_category_sina() 函数获取
    :type symbol: str
    :return: 日行情数据
    :rtype: pandas.DataFrame
    """
    url = (
        f"https://finance.sina.com.cn/realstock/company/{symbol}/hisdata_klc2/klc_kl.js"
    )
    r = requests.get(url)
    js_code = py_mini_racer.MiniRacer()
    js_code.eval(hk_js_decode)
    dict_list = js_code.call(
        "d", r.text.split("=")[1].split(";")[0].replace('"', "")
    )  # 执行js解密代码
    temp_df = pd.DataFrame(dict_list)
    if temp_df.empty:  # 处理获取数据为空的问题
        return pd.DataFrame()
    temp_df["date"] = pd.to_datetime(temp_df["date"], errors="coerce").dt.tz_localize(
        None
    )
    temp_df["open"] = pd.to_numeric(temp_df["open"], errors="coerce")
    temp_df["high"] = pd.to_numeric(temp_df["high"], errors="coerce")
    temp_df["low"] = pd.to_numeric(temp_df["low"], errors="coerce")
    temp_df["close"] = pd.to_numeric(temp_df["close"], errors="coerce")
    temp_df["volume"] = pd.to_numeric(temp_df["volume"], errors="coerce")

    # 转换日期列为日期类型
    temp_df["date"] = temp_df["date"].dt.date
    temp_df = temp_df.sort_values(by="date", ascending=True)
    return temp_df


def fund_etf_dividend_sina(symbol: str = "sh510050") -> pd.DataFrame:
    """
    新浪财经-基金-ETF 基金-累计分红
    https://finance.sina.com.cn/fund/quotes/510050/bc.shtml
    :param symbol: 基金名称, 可以通过 ak.fund_etf_category_sina() 函数获取
    :type symbol: str
    :return: 累计分红
    :rtype: pandas.DataFrame
    """
    # 构建复权数据URL
    factor_url = f"https://finance.sina.com.cn/realstock/company/{symbol}/hfq.js"
    r = requests.get(factor_url)
    text = r.text
    if text.startswith("var"):
        json_str = text.split("=")[1].strip().rsplit("}", maxsplit=1)[0].strip()
        data = eval(json_str + "}")  # 这里使用eval而不是json.loads因为数据格式特殊

        if isinstance(data, dict) and "data" in data:
            df = pd.DataFrame(data["data"])
            # 重命名列
            df.columns = ["date", "f", "s", "u"] if len(df.columns) == 4 else df.columns
            # 移除1900-01-01的数据
            df = df[df["date"] != "1900-01-01"]
            # 转换日期
            df["date"] = pd.to_datetime(df["date"])
            # 转换数值类型
            df[["f", "s", "u"]] = df[["f", "s", "u"]].astype(float)
            # 按日期排序
            df = df.sort_values(by="date", ascending=True, ignore_index=True)
            temp_df = df[["date", "u"]].copy()
            temp_df.columns = ["日期", "累计分红"]
            temp_df["日期"] = pd.to_datetime(temp_df["日期"], errors="coerce").dt.date
            return temp_df
        else:
            return pd.DataFrame()
    else:
        return pd.DataFrame()


if __name__ == "__main__":
    fund_etf_category_sina_df = fund_etf_category_sina(symbol="封闭式基金")
    print(fund_etf_category_sina_df)

    fund_etf_category_sina_df = fund_etf_category_sina(symbol="ETF基金")
    print(fund_etf_category_sina_df)

    fund_etf_category_sina_df = fund_etf_category_sina(symbol="LOF基金")
    print(fund_etf_category_sina_df)

    fund_etf_hist_sina_df = fund_etf_hist_sina(symbol="sh510050")
    print(fund_etf_hist_sina_df)

    fund_etf_dividend_sina_df = fund_etf_dividend_sina(symbol="sh510050")
    print(fund_etf_dividend_sina_df)
