"""
基金数据API基础模块

提供统一的基金数据查询和处理基础类，消除try/except重复模式
"""

from abc import ABC, abstractmethod
from functools import lru_cache
from typing import Optional, Union, List, Set, Dict, Any
import pandas as pd
from sqlalchemy import func

from sangreal_wind.utils.base_api import BaseAPI
from sangreal_wind.utils.config_manager import WIND_DB
from sangreal_wind.sangreal_calendar import CALENDAR


class FundDataAPI(BaseAPI):
    """基金数据API基础类"""

    def get_table_name(self) -> str:
        """获取基金净值表名"""
        return "CHINAMUTUALFUNDNAV"

    def get_table(self):
        """获取基金净值表对象"""
        return getattr(self.db, self.get_table_name())

    def safe_substring_filter(self, query, table, fund_list):
        """统一的基金代码过滤，处理substring/substr兼容性

        Args:
            query: 查询对象
            table: 数据库表对象
            fund_list: 基金代码列表

        Returns:
            过滤后的查询对象
        """
        if isinstance(fund_list, str):
            fund_code = fund_list[:6]
            # 🎯 优雅地处理数据库兼容性问题
            try:
                return query.filter(
                    func.substring(table.F_INFO_WINDCODE, 1, 6) == fund_code
                )
            except:
                return query.filter(
                    func.substr(table.F_INFO_WINDCODE, 1, 6) == fund_code
                )
        elif fund_list is not None:
            fund_codes = [f[:6] for f in fund_list]
            try:
                return query.filter(
                    func.substring(table.F_INFO_WINDCODE, 1, 6).in_(fund_codes)
                )
            except:
                return query.filter(
                    func.substr(table.F_INFO_WINDCODE, 1, 6).in_(fund_codes)
                )
        return query

    def create_fund_nav_query(self, begin_dt: str, end_dt: str):
        """创建基金净值查询

        Args:
            begin_dt: 开始日期
            end_dt: 结束日期

        Returns:
            基础查询对象
        """
        table = self.get_table()
        return self.db.query(
            table.F_INFO_WINDCODE,
            table.PRICE_DATE,
            table.F_NAV_ADJFACTOR,
            table.F_NAV_UNIT,
        ).filter(
            table.PRICE_DATE >= begin_dt,
            table.PRICE_DATE <= end_dt
        ).order_by(table.PRICE_DATE, table.F_INFO_WINDCODE)

    def process_fund_nav_dataframe(self, df) -> pd.DataFrame:
        """处理基金净值DataFrame

        Args:
            df: 原始DataFrame

        Returns:
            处理后的DataFrame
        """
        df.columns = ["f_sid", "trade_dt", "adjfactor", "unit"]
        df["s_close"] = df["adjfactor"] * df["unit"]
        df.drop(["unit", "adjfactor"], axis=1, inplace=True)

        # 🎯 统一的交易日过滤
        trade_dt_list = CALENDAR.dates
        df = df[df.trade_dt.isin(trade_dt_list)].reset_index(drop=True)
        return df

    @abstractmethod
    def get_fund_data(self, *args, **kwargs) -> pd.DataFrame:
        """获取基金数据，子类必须实现

        Returns:
            基金数据DataFrame
        """
        pass


class MutualFundNAVAPI(FundDataAPI):
    """共同基金净值API"""

    @lru_cache(maxsize=128)
    def get_fund_data(self, fund_list: Optional[Union[str, List[str], Set[str]]] = None,
                     begin_dt: str = "20010101", end_dt: str = "20990101") -> pd.DataFrame:
        """获取基金净值数据

        Args:
            fund_list: 基金代码
            begin_dt: 开始日期
            end_dt: 结束日期

        Returns:
            基金净值DataFrame
        """
        # 🎯 使用统一的查询构建方法
        query = self.create_fund_nav_query(begin_dt, end_dt)
        query = self.safe_substring_filter(query, self.get_table(), fund_list)

        df = query.to_df()
        return self.process_fund_nav_dataframe(df)


# 创建全局API实例
_fund_nav_api = MutualFundNAVAPI()

__all__ = [
    'FundDataAPI',
    'MutualFundNAVAPI',
    '_fund_nav_api'
]