"""Pro Bar (通用行情) interface.

Fetch A-share stock market data with adjustment factors from Tushare.
This interface provides backward-adjusted (后复权) daily market data
including all available fields: base price data, turnover rate (turnover_rate),
volume ratio (volume_ratio), and adjustment factors.
"""

import pandas as pd
from typing import Optional, List, Literal, Dict

from src.data.client import TushareClient
from src.data.api_wrappers.base_sync import StockBasedSync


def get_pro_bar(
    ts_code: str,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    asset: Literal["E", "I", "C", "FT", "FD", "O", "CB"] = "E",
    adj: Literal[None, "qfq", "hfq"] = "hfq",
    freq: Literal["D", "W", "M"] = "D",
    ma: Optional[List[int]] = None,
    factors: Optional[List[Literal["tor", "vr"]]] = None,
    adjfactor: bool = True,
    client: Optional[TushareClient] = None,
) -> pd.DataFrame:
    """Fetch pro bar (universal market) data from Tushare.

    This interface retrieves stock market data with adjustment factors.
    By default, it fetches backward-adjusted (后复权) daily data for stocks
    with turnover rate and volume ratio factors enabled.

    Args:
        ts_code: Stock code (e.g., '000001.SZ', '600000.SH')
        start_date: Start date in YYYYMMDD format
        end_date: End date in YYYYMMDD format
        asset: Asset type - 'E' (stock), 'I' (index), 'C' (crypto),
               'FT' (futures), 'FD' (fund), 'O' (options), 'CB' (convertible bond)
        adj: Adjustment type - None (no adjustment), 'qfq' (forward),
             'hfq' (backward). Default is 'hfq' (backward-adjusted).
        freq: Data frequency - 'D' (daily), 'W' (weekly), 'M' (monthly)
        ma: List of moving average periods (e.g., [5, 10, 20])
        factors: List of factors to include - 'tor' (turnover rate), 'vr' (volume ratio).
                 Default is ['tor', 'vr'] to fetch all available fields.
        adjfactor: Whether to include adjustment factor column. Default is True.
        client: Optional TushareClient instance for shared rate limiting.
                If None, creates a new client. For concurrent sync operations,
                pass a shared client to ensure proper rate limiting.

    Returns:
        pd.DataFrame with columns:
        - ts_code: Stock code
        - trade_date: Trade date (YYYYMMDD)
        - open: Opening price
        - high: Highest price
        - low: Lowest price
        - close: Closing price
        - pre_close: Previous closing price (adjusted)
        - change: Price change amount
        - pct_chg: Price change percentage
        - vol: Trading volume (lots)
        - amount: Trading amount (thousand CNY)
        - turnover_rate: Turnover rate (if factors includes 'tor')
        - volume_ratio: Volume ratio (if factors includes 'vr')
        - adj_factor: Adjustment factor (if adjfactor=True)
        - ma_X: Moving average price for period X (if ma specified)
        - ma_v_X: Moving average volume for period X (if ma specified)

    Example:
        >>> # Get backward-adjusted daily data with all factors (default)
        >>> data = get_pro_bar('000001.SZ', start_date='20240101', end_date='20240131')
        >>>
        >>> # Get unadjusted data
        >>> data = get_pro_bar('000001.SZ', start_date='20240101', adj=None)
        >>>
        >>> # Get data with moving averages
        >>> data = get_pro_bar('000001.SZ', start_date='20240101', ma=[5, 10, 20])
        >>>
        >>> # Get index data
        >>> data = get_pro_bar('000001.SH', asset='I', start_date='20240101')
    """
    client = client or TushareClient()

    # Build parameters
    params = {"ts_code": ts_code}

    if start_date:
        params["start_date"] = start_date
    if end_date:
        params["end_date"] = end_date
    if asset:
        params["asset"] = asset
    if adj:
        params["adj"] = adj
    if freq:
        params["freq"] = freq
    if ma:
        # Tushare expects ma as comma-separated string
        if isinstance(ma, list):
            ma_str = ",".join(str(m) for m in ma)
        else:
            ma_str = str(ma)
        params["ma"] = ma_str

    # Default to fetching all factors if not specified
    factors_to_use = factors if factors is not None else ["tor", "vr"]
    if factors_to_use:
        # Tushare expects factors as comma-separated string
        if isinstance(factors_to_use, list):
            factors_str = ",".join(factors_to_use)
        else:
            factors_str = factors_to_use
        params["factors"] = factors_str

    if adjfactor:
        params["adjfactor"] = "True"

    # Fetch data using pro_bar API
    data = client.query("pro_bar", **params)

    # Rename date column if needed
    if "date" in data.columns:
        data = data.rename(columns={"date": "trade_date"})

    return data


class ProBarSync(StockBasedSync):
    """Pro Bar 数据批量同步管理器，支持全量/增量同步。

    继承自 StockBasedSync，使用多线程按股票并发获取数据。
    默认获取全部数据列（turnover_rate, volume_ratio, adj_factor）。

    Example:
        >>> sync = ProBarSync()
        >>> results = sync.sync_all()  # 增量同步
        >>> results = sync.sync_all(force_full=True)  # 全量同步
        >>> preview = sync.preview_sync()  # 预览
    """

    table_name = "pro_bar"

    # 表结构定义
    TABLE_SCHEMA = {
        "ts_code": "VARCHAR(16) NOT NULL",
        "trade_date": "DATE NOT NULL",
        "open": "DOUBLE",
        "high": "DOUBLE",
        "low": "DOUBLE",
        "close": "DOUBLE",
        "pre_close": "DOUBLE",
        "change": "DOUBLE",
        "pct_chg": "DOUBLE",
        "vol": "DOUBLE",
        "amount": "DOUBLE",
        "turnover_rate": "DOUBLE",
        "volume_ratio": "DOUBLE",
        "adj_factor": "DOUBLE",
    }

    # 索引定义
    TABLE_INDEXES = [
        ("idx_pro_bar_date_code", ["trade_date", "ts_code"]),
    ]

    # 主键定义
    PRIMARY_KEY = ("ts_code", "trade_date")

    def fetch_single_stock(
        self,
        ts_code: str,
        start_date: str,
        end_date: str,
    ) -> pd.DataFrame:
        """获取单只股票的 Pro Bar 数据。

        Args:
            ts_code: 股票代码
            start_date: 起始日期（YYYYMMDD）
            end_date: 结束日期（YYYYMMDD）

        Returns:
            包含 Pro Bar 数据的 DataFrame
        """
        # 使用 get_pro_bar 获取数据（默认包含所有字段，传递共享 client）
        data = get_pro_bar(
            ts_code=ts_code,
            start_date=start_date,
            end_date=end_date,
            client=self.client,  # 传递共享客户端以确保限流
        )
        return data


def sync_pro_bar(
    force_full: bool = False,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    max_workers: Optional[int] = None,
    dry_run: bool = False,
) -> Dict[str, pd.DataFrame]:
    """同步所有股票的 Pro Bar 数据。

    这是 Pro Bar 数据同步的主要入口点。

    Args:
        force_full: 若为 True，强制从 20180101 完整重载
        start_date: 手动指定起始日期（YYYYMMDD）
        end_date: 手动指定结束日期（默认为今天）
        max_workers: 工作线程数（默认: 10）
        dry_run: 若为 True，仅预览将要同步的内容，不写入数据

    Returns:
        映射 ts_code 到 DataFrame 的字典

    Example:
        >>> # 首次同步（从 20180101 全量加载）
        >>> result = sync_pro_bar()
        >>>
        >>> # 后续同步（增量 - 仅新数据）
        >>> result = sync_pro_bar()
        >>>
        >>> # 强制完整重载
        >>> result = sync_pro_bar(force_full=True)
        >>>
        >>> # 手动指定日期范围
        >>> result = sync_pro_bar(start_date='20240101', end_date='20240131')
        >>>
        >>> # 自定义线程数
        >>> result = sync_pro_bar(max_workers=20)
        >>>
        >>> # Dry run（仅预览）
        >>> result = sync_pro_bar(dry_run=True)
    """
    sync_manager = ProBarSync(max_workers=max_workers)
    return sync_manager.sync_all(
        force_full=force_full,
        start_date=start_date,
        end_date=end_date,
        dry_run=dry_run,
    )


def preview_pro_bar_sync(
    force_full: bool = False,
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    sample_size: int = 3,
) -> dict:
    """预览 Pro Bar 同步数据量和样本（不实际同步）。

    这是推荐的方式，可在实际同步前检查将要同步的内容。

    Args:
        force_full: 若为 True，预览全量同步（从 20180101）
        start_date: 手动指定起始日期（覆盖自动检测）
        end_date: 手动指定结束日期（默认为今天）
        sample_size: 预览用样本股票数量（默认: 3）

    Returns:
        包含预览信息的字典：
        {
            'sync_needed': bool,
            'stock_count': int,
            'start_date': str,
            'end_date': str,
            'estimated_records': int,
            'sample_data': pd.DataFrame,
            'mode': str,  # 'full', 'incremental', 'partial', 或 'none'
        }

    Example:
        >>> # 预览将要同步的内容
        >>> preview = preview_pro_bar_sync()
        >>>
        >>> # 预览全量同步
        >>> preview = preview_pro_bar_sync(force_full=True)
        >>>
        >>> # 预览更多样本
        >>> preview = preview_pro_bar_sync(sample_size=5)
    """
    sync_manager = ProBarSync()
    return sync_manager.preview_sync(
        force_full=force_full,
        start_date=start_date,
        end_date=end_date,
        sample_size=sample_size,
    )
