#!/usr/bin/env python
# -*- coding: utf-8 -*-
# time: 2023/3/13 9:24
# file: dbUtils.py
# author: David
# company: shenyang JY
import os
import pandas as pd
import numpy as np
import datetime
import pickle
from request import requestHandler

current_path = os.path.dirname(__file__)


def readVar(path):
    if os.path.exists(path):
        with open(path, "rb") as file:
            var = pickle.load(file)
        return var
    else:
        return None


class dqFix(object):
    # 将误差存储为静态变量

    def __init__(self, log, args):
        self.logger = log
        self.args = args
        self.opt = self.args.parse_args_and_yaml()

    def history_error(self, history_dq, history_rp, dq):
        his = self.opt.history_hours * 5
        errors = pd.merge(history_dq, history_rp, on='C_TIME')
        errors = errors.tail(his)
        if len(errors) > 0:
            errors = errors.apply(pd.to_numeric, errors='ignore')
            error = errors['C_REAL_VALUE'].values - errors['C_FP_VALUE'].values
            error = round(np.mean(error), 3)
        else:
            error = 0
        print("---error&errors---:", error, errors)
        dq['his_fix'] = error + dq['C_FP_VALUE']
        dq.loc[dq['his_fix'] < 0, ['his_fix']] = 0
        dq.loc[dq['his_fix'] > self.opt.cap, ['his_fix']] = self.opt.cap
        dq['C_TIME'] = pd.to_datetime(dq['C_TIME'])
        return dq.loc[:, ['C_TIME', 'his_fix', 'C_FP_VALUE']]

    def history_error_clock(self, dq, rp, point):
        history_fixes = []
        for index, row in dq.iterrows():
            history_fix = row['C_FP_VALUE']
            time_end = row.iloc[0] - pd.Timedelta(hours=4) + point*pd.Timedelta(minutes=15)
            time_start = time_end - pd.Timedelta(hours=self.opt.history_hours)
            history = rp[(rp.C_TIME <= time_end) & (rp.C_TIME > time_start)].copy()  # rp已过滤限电时段
            if self.opt.usable_power['api_able_power'] is True:
                history['error'] = history['C_ABLE_VALUE'] - history['C_FP_VALUE']
            else:
                history['error'] = history['C_REAL_VALUE'] - history['C_FP_VALUE']
            history_err = round(history.loc[:, 'error'].mean(), 3) if len(history) != 0 else 0
            history_fix += history_err
            history_fix = history_fix if history_fix > 0 else 0
            history_fix = self.opt.cap if history_fix > self.opt.cap else history_fix
            history_fixes.append(history_fix)
        return history_fixes

    def cdq(self, fhs):
        cdq = []
        sun_up_time = datetime.datetime.strptime(self.opt.first_point['sun_up_time'], '%Y-%m-%d %H:%M:%S')
        for i, fh in fhs.iterrows():
            if i+1 > 16:
                T = 'T16'
            else:
                T = 'T' + str(i+1)
            coe_m = float(self.opt.coe[T]['m'])
            coe_n = float(self.opt.coe[T]['n'])
            dt = fh['C_TIME']
            dq = fh['C_FP_VALUE']
            dq_fix = fh['dq_fix']
            his_fix = fh['his_fix']
            new_dq = round(coe_n * his_fix + coe_m * dq_fix, 2)  # 修改曲线为0问题

            for i, cal in enumerate(self.opt.spot_trading):
                if 'T' + str(cal['point']) == T:
                    new_dq = round(new_dq * cal['coe'] + cal['abs'], 2)
                    self.logger.info("现货交易：第{}个点，进行了乘系数加绝对值修改".format(cal['point']))

            for i, cal in enumerate(self.opt.calculate):
                interval = list(range(cal['extraMinRange'], cal['extraMaxRange'] + 1))
                if dt.hour in interval:
                    new_dq = round(new_dq * cal['coe'] + cal['abs'], 2)
                    self.logger.info("第{}组，时段为：{}-{}点，时刻：{}，进行了乘系数加绝对值修改".format(i + 1, cal['extraMinRange'],
                                                                                        cal['extraMaxRange'], dt.strftime('%Y-%m-%d %H:%M:%S')))
            new_dq = new_dq if dq > 0 else 0
            new_dq = new_dq if new_dq > 0 else 0
            new_dq = self.opt.cap if new_dq > self.opt.cap else new_dq
            if T == 'T1' and self.opt.first_point['switch'] is True:
                # 华东特殊规则，第一个点用实际功率替换，日出用昨日日出点替换(系统判断是否限电能接尽接)
                if dt.time() != sun_up_time.time() or new_dq > 0:
                    rpt = requestHandler.history_rp.tail(1)
                    new_dq = rpt['C_ABLE_VALUE'].iloc[0] if rpt['LIMIT_STATUS'].iloc[0] == 1 else rpt['C_REAL_VALUE'].iloc[0]
                else:
                    new_dq = self.opt.first_point['sun_up_value']
            cdq.append({"C_TIME": dt.strftime('%Y-%m-%d %H:%M:%S'), "CDQ_VALUE": new_dq})
        return cdq


if __name__ == "__main__":
    import argparse
    # argparse方便于命令行下输入参数，可以根据需要增加更多
    parser = argparse.ArgumentParser()
    # parser.add_argument("-t", "--do_train", default=False, type=bool, help="whether to train")
    # parser.add_argument("-p", "--do_predict", default=True, type=bool, help="whether to train")
    # parser.add_argument("-b", "--batch_size", default=64, type=int, help="batch size")
    # parser.add_argument("-e", "--epoch", default=20, type=int, help="epochs num")
    args = parser.parse_args()

    #
    # for key in dir(args):               # dir(args) 函数获得args所有的属性
    #     if not key.startswith("_"):     # 去掉 args 自带属性，比如__name__等
    #         setattr(con, key, getattr(args, key))   # 将属性值赋给Config
    #
    # # main(con)
