import datetime as dt
from chinese_calendar import is_workday
from abc import ABC, abstractmethod
from logger_config import get_logger
from position_manager import PositionManager
from typing import Dict
from config import Config
import os

# 获取日志记录器

class BaseTrader(ABC):
    """交易基类，定义交易接口的通用方法"""
    
    def __init__(self, logger):
        """初始化交易基类"""
        self.position_managers: Dict[str, PositionManager] = {}
        self.logger = logger
        self._load_all_position_managers_from_data_dir()  # 新增：自动加载所有持仓管理器
        pass

    @abstractmethod
    def is_logged_in(self):
        """检查交易系统是否已经登录
        
        Returns:
            bool: True表示已登录，False表示未登录
        """
        pass
    
    @abstractmethod
    def login(self):
        """登录交易系统
        
        Returns:
            bool: 登录是否成功
        """
        pass

    @abstractmethod
    def logout(self):
        """登出交易系统"""
        pass

    @abstractmethod
    def get_balance(self):
        """获取账户资金情况
        
        Returns:
            dict: 账户资金信息，若失败返回None
        """
        pass

    @abstractmethod
    def get_positions(self):
        """获取所有持仓
        
        Returns:
            list: 持仓列表，若无持仓返回空列表
        """
        pass
        
    @abstractmethod
    def get_position(self, stock_code):
        """查询指定股票代码的持仓信息
        
        Args:
            stock_code: 股票代码，例如 "600000.SH"
            
        Returns:
            dict: 持仓详情，如果未持有则返回None
        """
        pass

    @abstractmethod
    def get_today_trades(self):
        """获取当日成交
        
        Returns:
            list: 成交列表，若无成交返回空列表
        """
        pass

    @abstractmethod
    def get_today_orders(self):
        """获取当日委托
        
        Returns:
            list: 委托列表，若无委托返回空列表
        """
        pass
        
    @abstractmethod
    def get_order(self, order_id):
        """查询指定订单ID的详细信息
        
        Args:
            order_id: 订单ID
            
        Returns:
            dict: 订单详情，如果未找到则返回None
        """
        pass

    @abstractmethod
    def buy(self, code, price, amount, order_type='limit'):
        """买入股票
        
        Args:
            code: 股票代码
            price: 买入价格（市价单时可为0）
            amount: 买入数量
            order_type: 订单类型，'limit'=限价单，'market'=市价单，默认为'limit'
            
        Returns:
            dict: 包含订单ID的字典
        """
        pass

    @abstractmethod
    def sell(self, code, price, amount, order_type='limit'):
        """卖出股票
        
        Args:
            code: 股票代码
            price: 卖出价格（市价单时可为0）
            amount: 卖出数量
            order_type: 订单类型，'limit'=限价单，'market'=市价单，默认为'limit'
            
        Returns:
            dict: 包含订单ID的字典
        """
        pass

    @abstractmethod
    def cancel(self, order_id):
        """撤销订单
        
        Args:
            order_id: 订单ID
            
        Returns:
            dict: 撤单结果
        """
        pass

    @staticmethod
    def is_trading_time():
        """判断当前是否为交易时间
            
        Returns:
            bool: True 表示当前为交易时间，False 表示当前休市
        """
        try:
            now = dt.datetime.now()
            
            # 先判断是否为交易日
            if not BaseTrader.is_trading_date():
                return False
                
            # 判断是否在交易时间段内
            current_time = now.time()
            morning_start = dt.time(9, 30)  # 上午开市时间 9:30
            morning_end = dt.time(11, 30)   # 上午休市时间 11:30
            afternoon_start = dt.time(13, 0) # 下午开市时间 13:00
            afternoon_end = dt.time(15, 0)   # 下午休市时间 15:00
            
            # 判断是否在上午或下午的交易时段
            is_morning_session = morning_start <= current_time <= morning_end
            is_afternoon_session = afternoon_start <= current_time <= afternoon_end
            
            return is_morning_session or is_afternoon_session
            
        except Exception as e:
            logger = get_logger("BaseTrader")
            logger.error(f"判断交易时间发生错误: {str(e)}")
            return False
    
    @staticmethod
    def is_trading_date(date=None):
        """判断指定日期是否为交易日
        
        Args:
            date: 日期，默认为当前日期
            
        Returns:
            bool: True 表示是交易日，False 表示非交易日
        """
        try:
            # 如果未指定日期，使用当前日期
            if date is None:
                date = dt.datetime.now()
                
            # 使用 chinese_calendar 判断是否为工作日（考虑节假日和调休）
            return is_workday(date)
            
        except Exception as e:
            logger = get_logger("BaseTrader")
            logger.error(f"判断交易日期发生错误: {str(e)}")
            return False
        
    def get_position_manager(self, strategy_name) -> PositionManager:
        """获取指定策略的持仓管理器
        
        Args:
            strategy_name: 策略名称
        
        Returns:
            PositionManager: 指定策略的持仓管理器
        """
        if strategy_name not in self.position_managers:
            self.position_managers[strategy_name] = PositionManager(strategy_name)
        return self.position_managers[strategy_name]
    
    def get_all_position_managers(self) -> Dict[str, PositionManager]:
        """获取所有持仓管理器"""
        return self.position_managers
    
    def is_today(self, datetime: dt.datetime) -> bool:
        """判断指定日期是否为当前日期
        
        Args:
            datetime: 日期时间
            
        Returns:
            bool: True 表示是当前日期，False 表示不是当前日期
        """
        return datetime.date() == dt.datetime.now().date()
    
    def clear_position_manager(self, strategy_name):
        """清除指定策略的持仓管理器"""
        if strategy_name in self.position_managers:
            self.position_managers[strategy_name].clear()
            return True
        return False

    def _load_all_position_managers_from_data_dir(self):
        """从Config.DATA_DIR目录下的持仓文件自动加载所有PositionManager"""
        data_dir = Config.DATA_DIR
        if not os.path.exists(data_dir):
            self.logger.info(f"持仓数据目录不存在: {data_dir}")
            return
        for fname in os.listdir(data_dir):
            if fname.endswith('_positions.json'):
                strategy_name = fname[:-len('_positions.json')]
                try:
                    self.position_managers[strategy_name] = PositionManager(strategy_name)
                    self.logger.info(f"已自动加载策略持仓: {strategy_name}")
                except Exception as e:
                    self.logger.error(f"加载策略持仓失败: {strategy_name}, 错误: {e}")
