"""财务指标数据接口 (VIP 版本)

使用 Tushare VIP 接口 (fina_indicator_vip) 获取财务指标数据。
按季度同步，一次请求获取一个季度的全部上市公司数据。

接口说明:
- fina_indicator_vip: 获取某一季度全部上市公司财务指标数据
- 需要 5000 积分才能调用
- period 参数为报告期（季度最后一天，如 20231231）
- 每次请求最多返回 100 条记录（需多次请求获取更多数据）

使用方式:
    # 同步财务指标数据
    from src.data.api_wrappers.financial_data.api_fina_indicator import (
        FinaIndicatorQuarterSync,
        sync_fina_indicator
    )

    # 方式1: 使用类
    syncer = FinaIndicatorQuarterSync()
    syncer.sync_incremental()  # 增量同步
    syncer.sync_full()  # 全量同步

    # 方式2: 使用便捷函数
    sync_fina_indicator()  # 增量同步
    sync_fina_indicator(force_full=True)  # 全量同步
"""

from typing import Optional
import pandas as pd

from src.data.client import TushareClient
from src.data.api_wrappers.base_financial_sync import (
    QuarterBasedSync,
    sync_financial_data,
    preview_financial_sync,
)


class FinaIndicatorQuarterSync(QuarterBasedSync):
    """财务指标季度同步实现。

    使用 fina_indicator_vip 接口按季度获取全部上市公司财务指标数据。

    表结构: financial_fina_indicator
    主键: (ts_code, end_date)
    """

    table_name = "financial_fina_indicator"
    api_name = "fina_indicator_vip"

    # 目标报表类型：默认只同步合并报表（财务指标接口无需过滤 report_type）
    TARGET_REPORT_TYPE = None

    # 表结构定义 - 完整的财务指标字段
    TABLE_SCHEMA = {
        # 基础字段
        "ts_code": "VARCHAR(16) NOT NULL",
        "ann_date": "DATE",
        "end_date": "DATE NOT NULL",
        # 每股收益指标
        "eps": "DOUBLE",
        "dt_eps": "DOUBLE",
        "total_revenue_ps": "DOUBLE",
        "revenue_ps": "DOUBLE",
        "capital_rese_ps": "DOUBLE",
        "surplus_rese_ps": "DOUBLE",
        "undist_profit_ps": "DOUBLE",
        "extra_item": "DOUBLE",
        "profit_dedt": "DOUBLE",
        "gross_margin": "DOUBLE",
        # 偿债能力指标
        "current_ratio": "DOUBLE",
        "quick_ratio": "DOUBLE",
        "cash_ratio": "DOUBLE",
        # 营运能力指标
        "invturn_days": "DOUBLE",
        "arturn_days": "DOUBLE",
        "inv_turn": "DOUBLE",
        "ar_turn": "DOUBLE",
        "ca_turn": "DOUBLE",
        "fa_turn": "DOUBLE",
        "assets_turn": "DOUBLE",
        # 盈利能力指标
        "op_income": "DOUBLE",
        "valuechange_income": "DOUBLE",
        "interst_income": "DOUBLE",
        "daa": "DOUBLE",
        "ebit": "DOUBLE",
        "ebitda": "DOUBLE",
        "fcff": "DOUBLE",
        "fcfe": "DOUBLE",
        # 资本结构指标
        "current_exint": "DOUBLE",
        "noncurrent_exint": "DOUBLE",
        "interestdebt": "DOUBLE",
        "netdebt": "DOUBLE",
        "tangible_asset": "DOUBLE",
        "working_capital": "DOUBLE",
        "networking_capital": "DOUBLE",
        "invest_capital": "DOUBLE",
        "retained_earnings": "DOUBLE",
        # 每股指标
        "diluted2_eps": "DOUBLE",
        "bps": "DOUBLE",
        "ocfps": "DOUBLE",
        "retainedps": "DOUBLE",
        "cfps": "DOUBLE",
        "ebit_ps": "DOUBLE",
        "fcff_ps": "DOUBLE",
        "fcfe_ps": "DOUBLE",
        # 销售能力指标
        "netprofit_margin": "DOUBLE",
        "grossprofit_margin": "DOUBLE",
        "cogs_of_sales": "DOUBLE",
        "expense_of_sales": "DOUBLE",
        "profit_to_gr": "DOUBLE",
        "saleexp_to_gr": "DOUBLE",
        "adminexp_of_gr": "DOUBLE",
        "finaexp_of_gr": "DOUBLE",
        "impai_ttm": "DOUBLE",
        "gc_of_gr": "DOUBLE",
        "op_of_gr": "DOUBLE",
        "ebit_of_gr": "DOUBLE",
        # 投资回报率指标
        "roe": "DOUBLE",
        "roe_waa": "DOUBLE",
        "roe_dt": "DOUBLE",
        "roa": "DOUBLE",
        "npta": "DOUBLE",
        "roic": "DOUBLE",
        "roe_yearly": "DOUBLE",
        "roa2_yearly": "DOUBLE",
        "roe_avg": "DOUBLE",
        # 利润结构指标
        "opincome_of_ebt": "DOUBLE",
        "investincome_of_ebt": "DOUBLE",
        "n_op_profit_of_ebt": "DOUBLE",
        "tax_to_ebt": "DOUBLE",
        "dtprofit_to_profit": "DOUBLE",
        # 现金流量指标
        "salescash_to_or": "DOUBLE",
        "ocf_to_or": "DOUBLE",
        "ocf_to_opincome": "DOUBLE",
        # 资本支出指标
        "capitalized_to_da": "DOUBLE",
        # 杠杆与偿债能力指标
        "debt_to_assets": "DOUBLE",
        "assets_to_eqt": "DOUBLE",
        "dp_assets_to_eqt": "DOUBLE",
        "ca_to_assets": "DOUBLE",
        "nca_to_assets": "DOUBLE",
        "tbassets_to_totalassets": "DOUBLE",
        "int_to_talcap": "DOUBLE",
        "eqt_to_talcapital": "DOUBLE",
        "currentdebt_to_debt": "DOUBLE",
        "longdeb_to_debt": "DOUBLE",
        "ocf_to_shortdebt": "DOUBLE",
        "debt_to_eqt": "DOUBLE",
        "eqt_to_debt": "DOUBLE",
        "eqt_to_interestdebt": "DOUBLE",
        "tangibleasset_to_debt": "DOUBLE",
        "tangasset_to_intdebt": "DOUBLE",
        "tangibleasset_to_netdebt": "DOUBLE",
        "ocf_to_debt": "DOUBLE",
        "ocf_to_interestdebt": "DOUBLE",
        "ocf_to_netdebt": "DOUBLE",
        "ebit_to_interest": "DOUBLE",
        "longdebt_to_workingcapital": "DOUBLE",
        "ebitda_to_debt": "DOUBLE",
        # 营运周期指标
        "turn_days": "DOUBLE",
        "roa_yearly": "DOUBLE",
        "roa_dp": "DOUBLE",
        "fixed_assets": "DOUBLE",
        # 利润质量指标
        "profit_prefin_exp": "DOUBLE",
        "non_op_profit": "DOUBLE",
        "op_to_ebt": "DOUBLE",
        "nop_to_ebt": "DOUBLE",
        "ocf_to_profit": "DOUBLE",
        # 流动性指标
        "cash_to_liqdebt": "DOUBLE",
        "cash_to_liqdebt_withinterest": "DOUBLE",
        "op_to_liqdebt": "DOUBLE",
        "op_to_debt": "DOUBLE",
        "roic_yearly": "DOUBLE",
        "total_fa_trun": "DOUBLE",
        "profit_to_op": "DOUBLE",
        # 单季度指标 (q_*)
        "q_opincome": "DOUBLE",
        "q_investincome": "DOUBLE",
        "q_dtprofit": "DOUBLE",
        "q_eps": "DOUBLE",
        "q_netprofit_margin": "DOUBLE",
        "q_gsprofit_margin": "DOUBLE",
        "q_exp_to_sales": "DOUBLE",
        "q_profit_to_gr": "DOUBLE",
        "q_saleexp_to_gr": "DOUBLE",
        "q_adminexp_to_gr": "DOUBLE",
        "q_finaexp_to_gr": "DOUBLE",
        "q_impair_to_gr_ttm": "DOUBLE",
        "q_gc_to_gr": "DOUBLE",
        "q_op_to_gr": "DOUBLE",
        "q_roe": "DOUBLE",
        "q_dt_roe": "DOUBLE",
        "q_npta": "DOUBLE",
        "q_opincome_to_ebt": "DOUBLE",
        "q_investincome_to_ebt": "DOUBLE",
        "q_dtprofit_to_profit": "DOUBLE",
        "q_salescash_to_or": "DOUBLE",
        "q_ocf_to_sales": "DOUBLE",
        "q_ocf_to_or": "DOUBLE",
        # 同比增长率指标 (*_yoy)
        "basic_eps_yoy": "DOUBLE",
        "dt_eps_yoy": "DOUBLE",
        "cfps_yoy": "DOUBLE",
        "op_yoy": "DOUBLE",
        "ebt_yoy": "DOUBLE",
        "netprofit_yoy": "DOUBLE",
        "dt_netprofit_yoy": "DOUBLE",
        "ocf_yoy": "DOUBLE",
        "roe_yoy": "DOUBLE",
        "bps_yoy": "DOUBLE",
        "assets_yoy": "DOUBLE",
        "eqt_yoy": "DOUBLE",
        "tr_yoy": "DOUBLE",
        "or_yoy": "DOUBLE",
        # 单季度增长指标 (q_*_yoy, q_*_qoq)
        "q_gr_yoy": "DOUBLE",
        "q_gr_qoq": "DOUBLE",
        "q_sales_yoy": "DOUBLE",
        "q_sales_qoq": "DOUBLE",
        "q_op_yoy": "DOUBLE",
        "q_op_qoq": "DOUBLE",
        "q_profit_yoy": "DOUBLE",
        "q_profit_qoq": "DOUBLE",
        "q_netprofit_yoy": "DOUBLE",
        "q_netprofit_qoq": "DOUBLE",
        # 其他指标
        "equity_yoy": "DOUBLE",
        "rd_exp": "DOUBLE",
        "update_flag": "VARCHAR(1)",
    }

    # 索引定义（不要创建唯一索引）
    # 注意：财务数据可能发生多次修正，不设置主键和唯一索引
    TABLE_INDEXES = [
        ("idx_financial_fina_indicator_ts_code", ["ts_code"]),
        ("idx_financial_fina_indicator_end_date", ["end_date"]),
        ("idx_financial_fina_indicator_ts_period", ["ts_code", "end_date"]),
    ]

    def __init__(self):
        """初始化财务指标同步器。"""
        super().__init__()
        self._fields = None  # 默认返回全部字段

    def fetch_single_quarter(self, period: str) -> pd.DataFrame:
        """获取单季度的全部上市公司财务指标数据。

        注意：fina_indicator_vip 接口每次请求最多返回 100 条记录，
        需要通过 offset 参数循环获取该季度的全部数据。

        Args:
            period: 报告期，季度最后一天日期（如 '20231231'）

        Returns:
            包含该季度全部上市公司财务指标数据的 DataFrame
        """
        all_data = []
        offset = 0
        limit = 100  # API 限制每次最多返回 100 条

        while True:
            params = {
                "period": period,
                "limit": limit,
                "offset": offset,
            }

            if self._fields:
                params["fields"] = self._fields

            df = self.client.query(self.api_name, **params)

            if df.empty:
                break

            all_data.append(df)

            # 如果返回的数据少于 limit，说明已经取完
            if len(df) < limit:
                break

            offset += limit

        if not all_data:
            return pd.DataFrame()

        return pd.concat(all_data, ignore_index=True)


# =============================================================================
# 便捷函数
# =============================================================================


def sync_fina_indicator(
    force_full: bool = False,
    dry_run: bool = False,
) -> list:
    """同步财务指标数据（便捷函数）。

    Args:
        force_full: 若为 True，强制全量同步
        dry_run: 若为 True，仅预览不写入

    Returns:
        同步结果列表

    Example:
        >>> # 增量同步
        >>> sync_fina_indicator()
        >>>
        >>> # 全量同步
        >>> sync_fina_indicator(force_full=True)
        >>>
        >>> # 预览
        >>> sync_fina_indicator(dry_run=True)
    """
    return sync_financial_data(FinaIndicatorQuarterSync, force_full, dry_run)


def preview_fina_indicator_sync() -> dict:
    """预览财务指标同步信息。

    Returns:
        预览信息字典
    """
    return preview_financial_sync(FinaIndicatorQuarterSync)


def get_fina_indicator(period: str, fields: Optional[str] = None) -> pd.DataFrame:
    """获取财务指标数据（原始接口，单季度）。

    用于直接获取某个季度的数据，不进行同步管理。
    注意：该接口每次最多返回 100 条记录，如需获取全部数据请使用同步功能。

    Args:
        period: 报告期，季度最后一天日期（如 '20231231'）
        fields: 指定返回字段，默认返回全部字段

    Returns:
        包含财务指标数据的 DataFrame
    """
    client = TushareClient()

    if fields is None:
        fields = (
            "ts_code,ann_date,end_date,eps,dt_eps,total_revenue_ps,revenue_ps,"
            "capital_rese_ps,surplus_rese_ps,undist_profit_ps,extra_item,profit_dedt,"
            "gross_margin,current_ratio,quick_ratio,cash_ratio,invturn_days,arturn_days,"
            "inv_turn,ar_turn,ca_turn,fa_turn,assets_turn,op_income,valuechange_income,"
            "interst_income,daa,ebit,ebitda,fcff,fcfe,current_exint,noncurrent_exint,"
            "interestdebt,netdebt,tangible_asset,working_capital,networking_capital,"
            "invest_capital,retained_earnings,diluted2_eps,bps,ocfps,retainedps,cfps,"
            "ebit_ps,fcff_ps,fcfe_ps,netprofit_margin,grossprofit_margin,cogs_of_sales,"
            "expense_of_sales,profit_to_gr,saleexp_to_gr,adminexp_of_gr,finaexp_of_gr,"
            "impai_ttm,gc_of_gr,op_of_gr,ebit_of_gr,roe,roe_waa,roe_dt,roa,npta,roic,"
            "roe_yearly,roa2_yearly,roe_avg,opincome_of_ebt,investincome_of_ebt,"
            "n_op_profit_of_ebt,tax_to_ebt,dtprofit_to_profit,salescash_to_or,"
            "ocf_to_or,ocf_to_opincome,capitalized_to_da,debt_to_assets,assets_to_eqt,"
            "dp_assets_to_eqt,ca_to_assets,nca_to_assets,tbassets_to_totalassets,"
            "int_to_talcap,eqt_to_talcapital,currentdebt_to_debt,longdeb_to_debt,"
            "ocf_to_shortdebt,debt_to_eqt,eqt_to_debt,eqt_to_interestdebt,"
            "tangibleasset_to_debt,tangasset_to_intdebt,tangibleasset_to_netdebt,"
            "ocf_to_debt,ocf_to_interestdebt,ocf_to_netdebt,ebit_to_interest,"
            "longdebt_to_workingcapital,ebitda_to_debt,turn_days,roa_yearly,roa_dp,"
            "fixed_assets,profit_prefin_exp,non_op_profit,op_to_ebt,nop_to_ebt,"
            "ocf_to_profit,cash_to_liqdebt,cash_to_liqdebt_withinterest,op_to_liqdebt,"
            "op_to_debt,roic_yearly,total_fa_trun,profit_to_op,q_opincome,"
            "q_investincome,q_dtprofit,q_eps,q_netprofit_margin,q_gsprofit_margin,"
            "q_exp_to_sales,q_profit_to_gr,q_saleexp_to_gr,q_adminexp_to_gr,"
            "q_finaexp_to_gr,q_impair_to_gr_ttm,q_gc_to_gr,q_op_to_gr,q_roe,q_dt_roe,"
            "q_npta,q_opincome_to_ebt,q_investincome_to_ebt,q_dtprofit_to_profit,"
            "q_salescash_to_or,q_ocf_to_sales,q_ocf_to_or,basic_eps_yoy,dt_eps_yoy,"
            "cfps_yoy,op_yoy,ebt_yoy,netprofit_yoy,dt_netprofit_yoy,ocf_yoy,roe_yoy,"
            "bps_yoy,assets_yoy,eqt_yoy,tr_yoy,or_yoy,q_gr_yoy,q_gr_qoq,q_sales_yoy,"
            "q_sales_qoq,q_op_yoy,q_op_qoq,q_profit_yoy,q_profit_qoq,q_netprofit_yoy,"
            "q_netprofit_qoq,equity_yoy,rd_exp,update_flag"
        )

    return client.query("fina_indicator_vip", period=period, fields=fields)
