"""Wind Linker 客户端"""

import os
import json
import requests
from typing import Any, List, Optional
from .config import get_api_url

try:
    import pandas as pd
    HAS_PANDAS = True
except ImportError:
    HAS_PANDAS = False


class WindData:
    """Wind 数据结果"""

    def __init__(self, data: dict):
        # 兼容两种格式: 服务端返回的小写字段和标准的大写字段
        self.ErrorCode = data.get("error_code", data.get("ErrorCode", -1))
        self.Codes = data.get("codes", data.get("Codes", []))
        self.Fields = data.get("fields", data.get("Fields", []))
        self.Times = data.get("times", data.get("Times", []))
        self.Data = data.get("data", data.get("Data", []))
        self.raw = data
    
    def to_df(self):
        """转换为 DataFrame"""
        if not HAS_PANDAS:
            raise ImportError("需要安装 pandas: pip install pandas")

        if not self.Data:
            return pd.DataFrame()

        # 构建 DataFrame
        df_data = {}

        # 添加字段数据
        for i, field in enumerate(self.Fields):
            if i < len(self.Data):
                df_data[field] = self.Data[i]

        # 创建 DataFrame
        df = pd.DataFrame(df_data)

        # 添加时间列
        if self.Times and len(self.Times) == len(df):
            df.insert(0, 'time', self.Times)

        # 添加代码列
        if self.Codes:
            if len(self.Codes) == 1:
                # 单个股票代码,重复填充
                df.insert(0, 'code', self.Codes[0])
            elif len(self.Codes) == len(df):
                # 多个股票代码,一一对应
                df.insert(0, 'code', self.Codes)

        return df
    
    def __repr__(self):
        return f"WindData(ErrorCode={self.ErrorCode}, Codes={self.Codes}, Fields={self.Fields})"


class WindAPI:
    """Wind API 客户端"""
    
    def __init__(self, base_url: Optional[str] = None, debug: bool = False):
        """
        初始化客户端

        Args:
            base_url: API 地址,默认从配置文件或环境变量读取
            debug: 是否开启调试模式
        """
        self.base_url = base_url or get_api_url()
        self.debug = debug
        self.session = requests.Session()
        self.session.headers.update({"Content-Type": "application/json"})
    
    def _execute(self, code: str) -> WindData:
        """执行 Wind 代码"""
        try:
            if self.debug:
                print(f"[DEBUG] 请求 URL: {self.base_url}/execute")
                print(f"[DEBUG] 请求代码: {code}")

            response = self.session.post(
                f"{self.base_url}/execute",
                json={"code": code},
                timeout=30
            )

            if self.debug:
                print(f"[DEBUG] 响应状态: {response.status_code}")
                print(f"[DEBUG] 响应内容: {response.text[:500]}")

            response.raise_for_status()
            result = response.json()

            # 如果返回的是错误信息,抛出异常
            if isinstance(result, dict) and result.get("ErrorCode", 0) != 0:
                error_msg = result.get("error", f"Wind API 错误 (ErrorCode: {result.get('ErrorCode')})")
                raise Exception(error_msg)

            return WindData(result)
        except requests.exceptions.RequestException as e:
            raise Exception(f"API 调用失败: {str(e)}")
        except Exception as e:
            if "API 调用失败" in str(e):
                raise
            raise Exception(f"处理响应失败: {str(e)}")
    
    def wsd(self, codes: str, fields: str, begin_time: str, end_time: str, options: str = "") -> WindData:
        """
        获取历史数据
        
        Args:
            codes: 股票代码,多个用逗号分隔
            fields: 字段,多个用逗号分隔
            begin_time: 开始日期
            end_time: 结束日期
            options: 可选参数
        
        Returns:
            WindData 对象
        
        Example:
            data = w.wsd("000001.SZ", "close", "2025-01-01", "2025-01-10")
            df = data.to_df()
        """
        code = f'w.wsd("{codes}", "{fields}", "{begin_time}", "{end_time}"'
        if options:
            code += f', "{options}"'
        code += ')'
        return self._execute(code)
    
    def wsi(self, codes: str, fields: str, begin_time: str, end_time: str, options: str = "") -> WindData:
        """
        获取分钟数据
        
        Args:
            codes: 股票代码
            fields: 字段,多个用逗号分隔
            begin_time: 开始时间
            end_time: 结束时间
            options: 可选参数
        
        Returns:
            WindData 对象
        
        Example:
            data = w.wsi("000001.SZ", "close,volume", "2025-01-10 09:30:00", "2025-01-10 15:00:00")
            df = data.to_df()
        """
        code = f'w.wsi("{codes}", "{fields}", "{begin_time}", "{end_time}"'
        if options:
            code += f', "{options}"'
        code += ')'
        return self._execute(code)
    
    def wsq(self, codes: str, fields: str = "rt_last") -> WindData:
        """
        获取实时行情
        
        Args:
            codes: 股票代码,多个用逗号分隔
            fields: 字段,多个用逗号分隔
        
        Returns:
            WindData 对象
        
        Example:
            data = w.wsq("000001.SZ,600000.SH", "rt_last,rt_vol")
            df = data.to_df()
        """
        code = f'w.wsq("{codes}", "{fields}")'
        return self._execute(code)
    
    def wset(self, tablename: str, options: str = "") -> WindData:
        """
        获取板块成分、指标数据
        
        Args:
            tablename: 数据集名称
            options: 可选参数
        
        Returns:
            WindData 对象
        
        Example:
            data = w.wset("sectorconstituent", "date=2025-01-10;sectorid=a001010100000000")
            df = data.to_df()
        """
        code = f'w.wset("{tablename}"'
        if options:
            code += f', "{options}"'
        code += ')'
        return self._execute(code)
    
    def execute(self, code: str) -> WindData:
        """
        执行自定义 Wind 代码
        
        Args:
            code: Wind 代码
        
        Returns:
            WindData 对象
        
        Example:
            data = w.execute('w.wsd("000001.SZ", "close", "2025-01-01", "2025-01-10")')
            df = data.to_df()
        """
        return self._execute(code)
    
    def batch(self, codes: List[str]) -> List[WindData]:
        """
        批量执行
        
        Args:
            codes: Wind 代码列表
        
        Returns:
            WindData 对象列表
        
        Example:
            results = w.batch([
                'w.wsd("000001.SZ", "close", "2025-01-01", "2025-01-10")',
                'w.wsd("600000.SH", "close", "2025-01-01", "2025-01-10")'
            ])
        """
        try:
            response = self.session.post(
                f"{self.base_url}/batch",
                json={"codes": codes},
                timeout=60
            )
            response.raise_for_status()
            return [WindData(item) for item in response.json()]
        except Exception as e:
            raise Exception(f"批量调用失败: {str(e)}")
    
    def health(self) -> dict:
        """健康检查"""
        try:
            response = self.session.get(f"{self.base_url}/health", timeout=5)
            response.raise_for_status()
            return response.json()
        except Exception as e:
            raise Exception(f"健康检查失败: {str(e)}")

