# -*- coding: utf-8 -*-
"""
Created on Fri Aug  5 15:29:12 2022

@author: MINGL
"""
import pandas as pd
import pyautogui as pyautogui
import pywinauto
from pywinauto import clipboard
from pywinauto import keyboard
from skimage import io
import time
import io as mio
import pytesseract
import warnings
import datetime
from tools import *

from connect_wifi import connect_wifi
from iptest import get_proxy_ip,set_global_proxy,get_ip_data



warnings.filterwarnings('ignore')
scripts_path = os.path.dirname(os.path.realpath(__file__))
root_path = scripts_path[:scripts_path.find(project_name)+len(project_name)]

path = r'C:\trade_software1\trade_software\goldsun\TdxW.exe'


class GXClientTrader:
    """
    基于通达信程序国信金太阳专业版自动交易程序
    """

    def __init__(self, account_name, exe_path=path):
        self.path = exe_path
        self.account_name = account_name
        self.log = Logger(f'{root_path}/logs',self.account_name)
        # 用户券商信息
        sql = f"select * from ainvest_usercount where username='{account_name}'"
        df_count = download_data_from_db(sql, 'ai_strategy_update_iddb')
        self.securities_name = str(df_count['securities_username'].tolist()[0])
        self.securities_password = str(df_count['securities_password'].tolist()[0])
        self.communication_password = str(df_count['communication_password'].tolist()[0])

    def exit(self):
        '''
        结束进程

        Returns
        -------
        None.

        '''
        self._app.kill()

    def login(self):
        '''
        启动软件并登录

        Returns
        -------
        None.

        '''
        #软件启动判断，若有进行中进程，先关闭再重启
        try:
            self._app = pywinauto.Application().connect(
                path=self.path, timeout=10
            )
            self.exit()
            self.log.warn('There are running programs, and there are processes in retreat')
        except Exception:
            pass

        #启动软件进程，输入账号密码
        self.log.info('Start login')
        broker = '国信证券'
        start_time = time.time()
        reset_proxy_to_default()  # 初始化proxy信息

        # 重置mac
        set_mac = SetMac()
        set_mac.run()
        if not connect_wifi('ZTE_A5DB9D', '1234567890'):  # 'Redmi K40','123456789'
            self.log.error("无法建立网络连接，请检查配置")
        else:
            self.log.info("网络已就绪")

        get_ip_times = 0
        writer = ExcelDataWriter()  # 初始化ip_records 表格
        used_ip = writer.get_unavailable_ips(broker, account_name)
        while get_ip_times < 3:
            try:
                item = get_ip_data()  # 获取动态IP
                if item['ip'] in used_ip:
                    get_ip_times += 1
                else:
                    self.log.info(f'代理IP已经获取{item}')
                    break
            except Exception as e:
                self.log.error(f'获取IP失败，请检查网络连接{e}')
                time.sleep(5)
                # raise ConnectionError(f"获取IP失败，请检查网络连接。错误详情: {e}")

        # 设置全局代理
        proxy_ip = item['ip']
        proxy_port = item['port']
        set_global_proxy(proxy_ip, proxy_port, enable=True)

        # exit_ip = get_proxy_ip(proxy_ip,proxy_port)
        time_with_change_proxy = time.time() - start_time
        self.log.info('全局代理设置成功')

        insert_data = {'as_of_date': datetime.datetime.fromtimestamp(start_time).strftime('%Y-%m-%d %H:%M:%S.%f'),
                       'broker': broker,
                       'account': account_name,
                       'proxy_ip': proxy_ip,
                       'proxy_port': proxy_port,
                       'ip_location': item['prov'] + ':' + item['city'],
                       # 'exit_ip': exit_ip,
                       'ip_cross_check_result': '一致',
                       'ip_switch_time': time_with_change_proxy,
                       # 'ip_expire_time':item['expire']
                       'ip_survival_time': '3min'
                       }
        # 写入数据表
        writer = ExcelDataWriter()  # 初始化ip_records 表格
        writer.write_data(insert_data)

        self._app = pywinauto.Application().start(self.path)
        while True:
            try:
                self._app.window(title_re='国信证券消息中心*').wait("ready")
                break
            except RuntimeError:
                pass
        tryrun(self._app.window(title='国信金太阳专业版V8.39 - [行情报价-自选股]').wait("ready"))

        self._app.window(title='国信证券消息中心'). minimize()
        self._app.window(title_re='国信金太阳专业版.*',class_name='TdxW_MainFrame_Class').window(control_id = 0x3001,class_name='#32770').window(control_id=0x3E9,class_name = 'AfxWnd100').click()
        # 输入账号
        self._app.window(title_re='国信金太阳专业版V8.39',class_name='#32770').window(control_id=0xE9, class_name='SafeEdit').click()
        time.sleep(1)
        pyautogui.typewrite(self.securities_name, interval=0.1)

        # 输入密码
        self._app.window(title_re='国信金太阳专业版V8.39',class_name='#32770').window(control_id=0xEA, class_name='SafeEdit').click()
        time.sleep(1)
        pyautogui.typewrite(self.securities_password, interval=0.1)

        #登录
        pywinauto.keyboard.send_keys("{ENTER}")

        time.sleep(3)

        # 设置主窗口及菜单窗口
        self.main_wnd = self._app.window(title_re='国信金太阳专业版.*',class_name='TdxW_MainFrame_Class')
        self.left_wnd = self.main_wnd.window(class_name='SysTreeView32', control_id=0xE900)

        tryrun(self.left_wnd.wait("ready"))

        # print(self.left_wnd.print_control_identifiers())
        # print(self.left_wnd.tree_root())

    def buy(self, stock_no, price, num):
        '''
        买入股票

        Parameters
        ----------
        stock_no : TYPE
            DESCRIPTION.
        price : TYPE
            DESCRIPTION.
        num : TYPE
            DESCRIPTION.

        Returns
        -------
        None.

        '''
        self.left_wnd.get_item([0]).click_input()
        self.__trade(stock_no, price, num)

    def sell(self, stock_no, price, num):
        '''
        卖出股票

        Parameters
        ----------
        stock_no : TYPE
            DESCRIPTION.
        price : TYPE
            DESCRIPTION.
        num : TYPE
            DESCRIPTION.

        Returns
        -------
        None.

        '''
        self.left_wnd.get_item([1]).click_input()
        self.__trade(stock_no, price, num)

    def purchase_stocks(self):

        self.left_wnd.get_item([5,2]).click_input()
        time.sleep(1)
        self.main_wnd.window(control_id=0x9876,class_name='Button').click()

        one_text = str(self._app.window(control_id=0x0, class_name="#32770",found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0]
        self.log.info(one_text.replace('/n', ' '))

        while True:
            try:
                self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x1B67,class_name="Button").click_input()

                self.log.info(str(self._app.window(title='提示', class_name="#32770", found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0])

            except:
                break

    def cancel_entrust(self):
        '''
        全撤

        Returns
        -------
        None.

        '''
        # # 进入撤单页面
        time.sleep(0.5)
        self.left_wnd.get_item([4]).click_input()        # 点击撤单
        time.sleep(1)
        # 刷新
        try:
            self.main_wnd.window(control_id=0x474, class_name='Button').click_input()
        except:
            self.main_wnd.window(control_id=0x474, class_name='Button').click()

        time.sleep(1)
        try:
            # 全选中
            self.main_wnd.window(control_id=0xE, class_name='Button').click()
        except:
            self.main_wnd.window(control_id=0xE, class_name='Button').click_input()

        time.sleep(1)
        # exit()
        # 全撤
        try:
            self.main_wnd.window(control_id=0x470, class_name='Button').click_input()
        except:
            self.main_wnd.window(control_id=0x470, class_name='Button').click()

        time.sleep(1)

        # 确认撤单
        pywinauto.keyboard.send_keys("{ENTER}")
        time.sleep(5)
        # 确认撤单2
        pywinauto.keyboard.send_keys("{ENTER}")
        time.sleep(5)
        # 确认撤单2
        pywinauto.keyboard.send_keys("{ESC}")
        time.sleep(0.5)
        pywinauto.keyboard.send_keys("{ENTER}")

    def get_balance(self):
        '''
        获取资金情况

        Returns
        -------
        record : TYPE
            DESCRIPTION.

        '''
        self.left_wnd.get_item([6, 0]).click_input()
        one_str = self.main_wnd.window(control_id=0x628, class_name='Static').window_text()
        balance_text = one_str.strip(' ').split('  ')
        result = {}
        for i in balance_text:
            i_dict = i.split(':')
            k = i_dict[0]
            v = i_dict[1]
            result[k] = v
        record = pd.DataFrame.from_dict(result, orient='index').T
        record = record[['可用', '参考市值', '资产']]
        record.rename(columns={'可用': 'cash', '参考市值': 'Position_amount', '资产': 'Total_account'}, inplace=True)
        record['As_Of_Date'] = datetime.date.today()
        record['Account_Name'] = self.account_name
        return record

    def get_position(self):
        '''
        获取持仓情况

        Returns
        -------
        df_position : TYPE
            DESCRIPTION.

        '''
        self.left_wnd.get_item([6, 0]).click_input()
        # 复制表格数据
        time.sleep(1)
        self._copy_data([6, 0])
        try:
            filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-","")} 资金股份查询.xls'
            self._delete_first_lines(filenme, 1)
            # 读文件
            df_position = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
            os.remove(filenme)
        except:
            self.log.info('--------------------------------------无当日持仓--------------------------------------')
            return pd.DataFrame()
        df_position.columns = [i.strip('=').strip('"') for i in list(df_position.columns)]
        df_position = df_position.applymap(lambda x: x.strip('=').strip('"') if isinstance(x,str) else x)
        df_position['证券代码'] = df_position['证券代码'].apply(lambda x: tranTicker(x))
        df_position = df_position[['证券代码','证券名称','实际数量','可卖数量','冻结数量','持仓成本价','当前价','最新市值','持仓盈亏','盈亏比例(%)']]


        df_position.rename(columns={"证券代码": "Ticker",
                                         "证券名称": "Ticker_name",
                                         "实际数量": "Number_transactions",
                                         "可卖数量": "cash",
                                         "冻结数量": "frozen_quantity",
                                         "持仓成本价": "cost_price",
                                         "当前价": "market_price",
                                         "最新市值": "market_value",
                                         "持仓盈亏": "profit_and_loss",
                                         "盈亏比例(%)": "profit_loss_ratio",
                                         }, inplace=True)
        df_position['As_Of_Date'] = datetime.date.today()
        df_position['Account_Name'] = self.account_name

        return df_position

    def get_order(self):
        '''
        获取委托情况

        Returns
        -------
        TYPE
            DESCRIPTION.

        '''
        self.left_wnd.get_item([6, 1]).click_input()
        # 复制表格数据
        time.sleep(1)
        self._copy_data([6, 1])
        try:
            filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-", "")} 当日委托查询.xls'
            self._delete_first_lines(filenme, 0)
            # 读文件
            df_order = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
            os.remove(filenme)
        except:
            self.log.info('--------------------------------------无当日委托--------------------------------------')
            return pd.DataFrame()
        df_order.columns = [i.strip('=').strip('"') for i in list(df_order.columns)]
        df_order = df_order.applymap(lambda x: x.strip('=').strip('"') if isinstance(x, str) else x)
        df_order['证券代码'] = df_order['证券代码'].apply(lambda x: tranTicker(x))
        return df_order

    def get_today_trades(self):
        '''
        获取当日成交

        Returns
        -------
        TYPE
            DESCRIPTION.

        '''
        self.left_wnd.get_item([6, 2]).click_input()
        # 复制表格数据
        time.sleep(1)
        self._copy_data([6, 2])
        try:
            filenme = f'C:\\Users\\Administrator\\Documents\\{str(datetime.date.today()).replace("-", "")} 当日成交查询.xls'
            self._delete_first_lines(filenme, 0)
            # 读文件
            df = pd.read_csv(filenme, encoding='gbk', sep='\t', engine='python', error_bad_lines=False)
            os.remove(filenme)
        except:
            self.log.info('--------------------------------------无当日成交--------------------------------------')
            return pd.DataFrame()
        df.columns = [i.strip('=').strip('"') for i in list(df.columns)]
        df = df.applymap(lambda x: x.strip('=').strip('"') if isinstance(x, str) else x)
        df['证券代码'] = df['证券代码'].apply(lambda x: tranTicker(x))

        df = df[['成交时间','证券代码','证券名称','买卖标志','成交数量','成交价格']]
        df['Account_Name'] = self.account_name
        df['As_Of_Date'] = datetime.date.today()
        df.rename(columns={'成交时间': 'Trade_time', '证券代码': 'Ticker', '证券名称': 'Ticker_name', '买卖标志': 'Operate',
                           '成交数量': 'Number_transactions',
                           '成交价格': 'Average_price'}, inplace=True)
        df['Operate'] = df['Operate'].apply(lambda x: '卖' if '卖' in x else '买')

        df['Ticker'] = df['Ticker'].apply(lambda x: tranTicker(str(x).replace('="', '').replace('"', '')))

        return df

    def __trade(self, stock_no, price, amount):
        '''
        交易输入函数

        Parameters
        ----------
        stock_no : TYPE
            DESCRIPTION.
        price : TYPE
            DESCRIPTION.
        amount : TYPE
            DESCRIPTION.

        Returns
        -------
        None.

        '''
        time.sleep(1)

        # 设置股票代码
        self.main_wnd.window(class_name='#32770',control_id=0x0,found_index=1).window(control_id=0x2EE5, class_name="Edit").set_text(str(stock_no))
        time.sleep(1)

        # 设置价格
        self.main_wnd.window(class_name='#32770',control_id=0x0,found_index=1).window(control_id=0x2EE6, class_name="Edit").set_text(str(price))
        time.sleep(1)

        # 设置股数目
        self.main_wnd.window(class_name='#32770',control_id=0x0,found_index=1).window(control_id=0x2EE7, class_name="Edit").set_text(str(amount))
        time.sleep(1)
        # exit()

        # 点击卖出or买入
        self.main_wnd.window(control_id=0x7DA, class_name="Button").click()
        time.sleep(1)
        one_text = str(self._app.window(control_id=0x0, class_name="#32770",found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0]
        self.log.info(one_text.replace('/n', ' '))

        while True:
            try:
                self._app.window(control_id=0x0, class_name="#32770", found_index=0).window(control_id=0x1B67,class_name="Button").click_input()

                self.log.info(str(self._app.window(title='提示', class_name="#32770", found_index=0).children()[4].context_help_id).split("'")[1].split("'")[0])

            except:
                break


    def _copy_data(self, path):
        self.left_wnd.get_item(path, exact=False).click_input(button=u'left', double=False, wheel_dist=0, pressed=u'')
        time.sleep(0.5)
        try:
            self.main_wnd.window(control_id=0x47F, class_name='Button').click()
            time.sleep(0.5)

            self._app['输出'].window(control_id=0xE9, class_name='Button').click()
        except Exception:
            print('无输出的数据！')
        # 确认
        pywinauto.keyboard.send_keys("{ENTER}")

    def _delete_first_lines(self, filename, pp):

        fin = open(filename, 'r')
        a = fin.readlines()
        fout = open(filename, 'w')
        if pp == 0:
            b = ''.join(a)
        else:
            b = ''.join(a[3:])
        fout.write(b)

if __name__ == '__main__':

    account_name = str('13927338222')
    a = GXClientTrader(account_name)
    a.login()

    # 买入
    # a.buy('600000', '7','100')

    # 卖出
    # a.sell('600835', '12.45','900')
    # print(a.get_order())

    # a.purchase_stocks()

    # # 获取当日实际持仓
    # print(a.get_position())
    #
    # # 获取资金情况
    # print(a.get_balance())
    #
    # # 获取当日成交
    # print(a.get_today_trades())
