import time
import json
import re
import pendulum
import datetime
import pandas as pd
from pot_libs.logger import log
from pot_libs.common.components.responses import success_res
from unify_api.modules.elec_charge.dao.syncretize_energy_es_dao import \
    load_compy_power, load_spfv_price
from unify_api.modules.elec_charge.dao.syncretize_energy_dao import \
    get_annual_sunshine_hours, get_p, insert_price_policy_data_dao, \
    inset_algorithm_power_factor_dao, get_elec_price_dao, \
    get_algorithm_power_factor_dao, get_max_demand_by_inlid
from unify_api.modules.elec_charge.components.syncretize_energy_cps import \
    PvEvaluateComputeResp, Optimizecurve, ElectrovalenceResp, \
    EssEvaluateComputeResp, OptCurve, PvEvaluateTwoResp
from unify_api.modules.elec_charge.utils.pv_evaluate_tool import PvEvaluateTool
from unify_api.modules.elec_charge.utils.ess_evaluate_tool import \
    EssEvaluateTool
from unify_api.utils.common_utils import ChineseCalendar
from unify_api.modules.elec_charge.utils.co2_response import get_co2_price
from unify_api.modules.common.dao.common_dao import inline_zdu_all_by_cid
from unify_api.modules.zhiwei_u.service.scope_operations_service import \
    dataframe_excl_download
from unify_api.modules.zhiwei_u.dao.order_operations_dao import \
    select_cname_by_cid


# 综合能源-光伏-页面
async def pv_evaluate_service(cid, start, end):
    try:
        start_list = start.split("-")
        end_list = end.split("-")
        pendulum_start = pendulum.date(int(start_list[0]),
                                       int(start_list[1]), 1)
        pendulum_end = pendulum.date(int(end_list[0]), int(end_list[1]), 1)
        day_num = pendulum_end.days_in_month
    except:
        return success_res(code=4008, msg="日期输入错误")
    if (pendulum_end - pendulum_start).in_months() < 1:
        return success_res(code=4008, msg="日期最少选择2个月")
    elif (pendulum_end - pendulum_start).in_months() > 12:
        return success_res(code=4008, msg="日期最多选择12个月")
    else:
        
        p_datas = await load_compy_power(cid, f"{start}-01",
                                         f"{end}-{day_num}")
        if not p_datas:
            return PvEvaluateTwoResp(kwh_slot=[], p_slot=[], p=[], kwh=[],
                                     electrovalence={}, sum_kwh_p="",
                                     sum_kwh_s="", rule="")
        p_slots = {"%02d:%02d" % (i, j): [] for i in range(24) for j in
                   range(0, 60, 15)}
        kwh_slots = {"%02d" % i: [] for i in range(24)}
        num, flag = 0, "00"
        for data in p_datas:
            create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
            if data["p"]:
                p_slots[create_time[11:16]].append(data["p"])
            if data["kwh"]:
                if flag == create_time[11:13]:
                    num += data["kwh"]
                else:
                    kwh_slots[flag].append(num)
                    num = data["kwh"]
                    flag = create_time[11:13]
        
        for key, value in kwh_slots.items():
            kwh_slots[key] = round(sum(value) / len(value), 2) if value else ""
        
        # 获取峰时段
        elec_price = await get_elec_price_dao(cid)
        if not elec_price:
            log.error(f"该厂还未设置电价, cid:{cid}, table:price_policy")
            return success_res(code=4008, msg="该厂还未设置电价")
        section_time_range = get_section_time_range(elec_price["quarters"])
        elecs = get_section_time_slot(section_time_range)
        # 峰时段总用电量
        sum_kwh_p = 0
        for p in elecs["p"]:
            mid_kwh = kwh_slots.get(p[:2], 0) or 0
            sum_kwh_p += mid_kwh
        return PvEvaluateTwoResp(
            kwh_slot=[f"{slot}:00" for slot in kwh_slots],
            p_slot=[slot for slot in p_slots],
            electrovalence=elecs,
            sum_kwh_p=round(sum_kwh_p, 2),
            p=[round(sum(p) / len(p), 2) if p else "" for p in
               p_slots.values()],
            kwh=list(kwh_slots.values()))


# 综合能源-光伏-测算
async def pv_evaluate_compute_service(download=None, url=None, **body):
    try:
        start_list = body.get("start").split("-")
        end_list = body.get("end").split("-")
        pendulum_start = pendulum.datetime(int(start_list[0]),
                                           int(start_list[1]), 1)
        pendulum_end = pendulum.datetime(int(end_list[0]), int(end_list[1]), 1)
        day_num = pendulum_end.days_in_month
    except:
        return success_res(code=4008, msg="日期输入错误")
    try:
        # 面积
        total_capacity = float(body.get("install_space")) * \
                         float(body.get("area_conversion_ratio"))
        # 工厂容量 =屋顶面积*折算系数*单位面积容量
        invest_capacity = total_capacity * body.get(
            "capacity_per_meter") / 1000
        if not invest_capacity:
            return success_res(code=4008,
                               msg="场地面积/面积折算系数/单位面积容量不能为0")
    except:
        return success_res(code=4008, msg="工厂容器参数有误")
    if (pendulum_end - pendulum_start).in_months() < 1:
        return success_res(code=4008, msg="日期最少选择2个月")
    elif (pendulum_end - pendulum_start).in_months() > 12:
        return success_res(code=4008, msg="日期最多选择12个月")
    else:
        # 获取年有效日照小时数
        hours = await get_annual_sunshine_hours(body.get("cid"))
        if not hours:
            log.error(f"未找到该城市日照时间 cid:{body.get('cid')}")
            return success_res(code=4008, msg="未找到该城市日照时间")
        annual_sunshine_hours = hours.get("annual_effective_hours")
        # 获取光伏典型出力曲线  负荷曲线df_pv
        ps = await get_p(body.get("cid"))
        if not ps:
            log.error(f"未找到该城市光伏典型出力曲线 cid:{body.get('cid')}")
            return success_res(code=4008, msg="未找到该城市光伏典型出力曲线")
        p_slots = {"%02d:%02d:00" % (i, j): [] for i in range(24) for j in
                   range(0, 60, 15)}
        df_pv_curve = [p["p"] for p in ps for _ in range(4)]
        df_pv = pd.DataFrame(
            {"quarter_time": list(p_slots.keys()), "pv_curve": df_pv_curve},
            columns=["quarter_time", "pv_curve"])
        # 获取电量和负荷15分钟数据
        datas = await load_compy_power(body.get("cid"),
                                       f"{body.get('start')}-01",
                                       f"{body.get('end')}-{day_num}")
        if not datas:
            return success_res(code=4008, msg="未找到数据")
        for data in datas:
            create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
            if data["p"]:
                p_slots[create_time[11:19]].append(data["p"])
        for index, value in p_slots.items():
            p_slots[index] = sum(value) / len(value) if value else None
        # 负荷曲线df_load
        df_load = pd.DataFrame({"quarter_time": list(p_slots.keys()),
                                "load_curve": list(p_slots.values())},
                               columns=["quarter_time", "load_curve"])
        # 获取这段时间平均价格
        charge_price, kwh_price = await load_spfv_price(body.get("cid"),
                                                        f"{body.get('start')}-01",
                                                        f"{body.get('end')}-{day_num}")
        spfv_price = charge_price / kwh_price if charge_price and kwh_price else 0
        pv_system = {
            "user_type": "工商业",  # 建筑类型
            "install_space": body.get("install_space"),  # 屋顶面积m2
            "area_conversion_ratio": body.get("area_conversion_ratio"),
            # 面积折算系数
            "capacity_per_meter": body.get("capacity_per_meter"),  # 单位面积容量
            "self_use_ratio": body.get("self_use_ratio"),  # 自发自用比例
            "efficiency": body.get("efficiency"),  # 发电效率
            "evaluate_year": body.get("evaluate_year"),  # 评估年限
            "first_3year_decay_rate": 0.015,  # 前3年衰减率
            "other_year_decay_rate": 0.008,  # 4-25年衰减率
            "annual_sunshine_hours": annual_sunshine_hours  # 年峰值日照小数数
        }
        
        price = {
            "rmb_per_wp": body.get("rmb_per_w"),  # 建设单价
            "maintenance_per_wp": body.get('maintenance_per_wp'),  # 运维单价
            "coal_in_grid": body.get("coal_in_grid"),  # 脱硫电价
            "self_use_price_discout": 1.0,  # 自发自用电价折扣
            "spfv_price": spfv_price,  # 测算时段平均电价
            "bank_interest": 0.085
        }
        log.info(f"pv_system:{pv_system}, price:{price}, "
                 f"invest_capacity:{invest_capacity}")
        obj = PvEvaluateTool(pv_system, price, invest_capacity, df_load, df_pv)
        obj.output()
        # 测算表
        evaluate_table = (
            obj.evaluate_table.where(obj.evaluate_table.notnull(),
                                     None)).round(2)
        # 下载
        if download:
            company = await select_cname_by_cid(body.get("cid"))
            table_name = f"{company['shortname']}_" \
                         f"{body.get('start')}_{body.get('end')}分布式光伏测算表"
            return await dataframe_excl_download(evaluate_table, table_name)
        # 碳排放(吨)  碳排放系数 0.67 2020年该指标为305.5g/kWh，及0.3055kg/kWh
        c_emissions = obj.first_year_kwh * 0.67 * 0.3055 / 1000
        # co2排放(吨) 碳元素（C）分子量为12，二氧化碳（CO2）分子量为44，两者折算比例为3.67
        co2_emissions = c_emissions * 3.67
        # 年收益 爬虫获取价格
        co2_price = await get_co2_price()
        year_earnings = co2_emissions * co2_price
        # 优化曲线
        curve = obj.curve
        curve["after_curve"] = curve["load_curve"] - curve["pv_curve"]
        curve = curve.round(2).where(curve.notnull(), None)
        optimizecurve = Optimizecurve(
            slot=curve["quarter_time"].values.tolist(),
            before_curve=curve["load_curve"].values.tolist(),
            after_curve=curve["after_curve"].values.tolist(),
            pv_curve=curve["pv_curve"].values.tolist()
        )
        # 累计碳减排 co2
        all_elec = sum(evaluate_table["年发电量"].values.tolist())
        all_c_emissions = all_elec * 0.67 * 0.3055 / 1000 * 3.67
        # 植树
        tree = all_c_emissions * 1000 / 18.3
        compute_table = evaluate_table.to_dict("records")
        return PvEvaluateComputeResp(
            optimize_curve=optimizecurve,
            compute_table=compute_table,
            invest_capacity=round(invest_capacity, 2),
            first_year_kwh=round(obj.first_year_kwh, 2),
            static_period=round(obj.static_period, 2),
            total_capacity=round(total_capacity, 2),
            invest_charge=round(obj.invest_charge, 2),
            c_emissions=round(c_emissions, 2),
            co2_emissions=round(co2_emissions, 2),
            year_earnings=round(year_earnings, 2),
            all_c_emissions=round(all_c_emissions, 2),
            tree=round(tree),
            download_url=url
        )


# 综合能源-储能-页面
async def ess_evaluate_service(cid, start, end, work_day):
    try:
        start_list = start.split("-")
        end_list = end.split("-")
        pendulum_start = pendulum.datetime(int(start_list[0]),
                                           int(start_list[1]), 1)
        pendulum_end = pendulum.datetime(int(end_list[0]), int(end_list[1]), 1)
        day_num = pendulum_end.days_in_month
    except:
        return success_res(code=4008, msg="日期输入错误")
    if (pendulum_end - pendulum_start).in_months() < 1:
        return success_res(code=4008, msg="日期最少选择2个月")
    elif (pendulum_end - pendulum_start).in_months() > 12:
        return success_res(code=4008, msg="日期最多选择12个月")
    else:
        elec = await get_elec_price_dao(cid)
        if not elec:
            rule = 1
        else:
            elec_list = [i for i in re.findall("p*", elec["quarters"]) if i]
            rule = 2 if len(elec_list) > 1 else 1
        
        p_datas = await load_compy_power(cid, f"{start}-01",
                                         f"{end}-{day_num}")
        if not p_datas:
            return PvEvaluateTwoResp(kwh_slot=[], p_slot=[], p=[], kwh=[],
                                     electrovalence={}, sum_kwh_p="",
                                     sum_kwh_s="", rule="")
        p_slots = {"%02d:%02d" % (i, j): [] for i in range(24) for j in
                   range(0, 60, 15)}
        kwh_slots = {"%02d" % i: [] for i in range(24)}
        num, flag = 0, "00"
        # 1全部 2工作日 3非工作日
        if work_day == 2:
            for data in p_datas:
                create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
                if ChineseCalendar(create_time[:10]).is_workday():
                    if data["p"]:
                        p_slots[create_time[11:16]].append(data["p"])
                    if data["kwh"]:
                        if flag == create_time[11:13]:
                            num += data["kwh"]
                        else:
                            kwh_slots[flag].append(num)
                            num = data["kwh"]
                            flag = create_time[11:13]
        elif work_day == 3:
            for data in p_datas:
                create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
                if not ChineseCalendar(create_time[:10]).is_workday():
                    if data["kwh"]:
                        if flag == create_time[11:13]:
                            num += data["kwh"]
                        else:
                            kwh_slots[flag].append(num)
                            num = data["kwh"]
                            flag = create_time[11:13]
                    if data["p"]:
                        p_slots[create_time[11:16]].append(
                            data["p"])
        else:
            for data in p_datas:
                create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
                if data["p"]:
                    p_slots[create_time[11:16]].append(data["p"])
                if data["kwh"]:
                    if flag == create_time[11:13]:
                        num += data["kwh"]
                    else:
                        kwh_slots[flag].append(num)
                        num = data["kwh"]
                        flag = create_time[11:13]
        for key, value in kwh_slots.items():
            kwh_slots[key] = round(sum(value) / len(value), 2) if value else ""
        # 获取峰时段
        elec_price = await get_elec_price_dao(cid)
        if not elec_price:
            log.error(f"该厂还未设置电价, cid:{cid}, table:price_policy")
            return success_res(code=4008, msg="该厂还未设置电价")
        section_time_range = get_section_time_range(elec_price["quarters"])
        elecs = get_section_time_slot(section_time_range)
        # 峰时段总用电量
        sum_kwh_p = 0
        for p in elecs["p"]:
            mid_kwh_p = kwh_slots.get(p[:2], 0) or 0
            sum_kwh_p += mid_kwh_p
        # 尖时段总用电量
        sum_kwh_s = ""
        if elec_price.get("price_s") and elecs.get("s"):
            sum_kwh_s = 0
            for s in elecs["s"]:
                mid_kwh_s = kwh_slots.get(s[:2], 0) or 0
                sum_kwh_s += mid_kwh_s
            sum_kwh_s = round(sum_kwh_s, 2)
        return PvEvaluateTwoResp(
            rule=rule, p_slot=[slot for slot in p_slots],
            kwh_slot=[f"{slot}:00" for slot in kwh_slots],
            electrovalence=elecs,
            sum_kwh_p=round(sum_kwh_p, 2),
            sum_kwh_s=sum_kwh_s,
            p=[round(sum(p) / len(p), 2) if p else "" for p in
               p_slots.values()],
            kwh=list(kwh_slots.values()))


# 综合能源-储能-测算
async def ess_evaluate_compute_service(download=None, url=None, **body):
    try:
        start_list = body.get("start").split("-")
        end_list = body.get("end").split("-")
        pendulum_start = pendulum.datetime(int(start_list[0]),
                                           int(start_list[1]), 1)
        pendulum_end = pendulum.datetime(int(end_list[0]), int(end_list[1]), 1)
        day_num = pendulum_end.days_in_month
    except:
        return success_res(code=4008, msg="日期输入错误")
    
    if (pendulum_end - pendulum_start).in_months() < 1:
        return success_res(code=4008, msg="日期最少选择2个月")
    elif (pendulum_end - pendulum_start).in_months() > 12:
        return success_res(code=4008, msg="日期最多选择12个月")
    else:
        # 查找电价
        elec_prices = await get_elec_price_dao(body.get("cid"))
        # elec_price = {key: ";".join(value) for key, value in elec_prices.items() if value}
        if not elec_prices:
            log.error(
                f"该厂还未设置电价, cid:{body.get('cid')}, table:price_policy")
            return success_res(code=4008, msg="该厂还未设置电价")
        section_time_range = get_section_time_range(elec_prices["quarters"])
        # 获取工厂容量
        inline_zdu_dic = await inline_zdu_all_by_cid(body.get("cid"))
        capacity = sum([inline["inline_tc"] if inline.get("inline_tc") else 0
                        for inline in inline_zdu_dic])
        # 需量信息
        inlids = [inline["inlid"] for inline in inline_zdu_dic]
        max_demand = await get_max_demand_by_inlid(inlids)
        max_demand_flag = False
        max_demand_pmax = 0
        if max_demand:
            max_demand_list = [json.loads(demand["has_space"])
                               for demand in max_demand if demand["has_space"]]
            for demand in max_demand_list:
                if len(demand) == 0:
                    continue
                if demand[0] and max_demand_flag is False:
                    max_demand_flag = True
                max_demand_pmax += demand[1]
        max_demand_var = {"flag": max_demand_flag, "pmax": max_demand_pmax}
        # 获取电量和负荷15分钟数据
        datas = await load_compy_power(body.get("cid"),
                                       f"{body.get('start')}-01",
                                       f"{body.get('end')}-{day_num}")
        if not datas:
            return success_res(code=4008, msg="未找到数据")
        p_slots = {"%02d:%02d:00" % (i, j): [] for i in range(24) for j in
                   range(0, 60, 15)}
        for data in datas:
            create_time = data["create_time"].strftime("%Y-%m-%d %H:%M:%S")
            # 1全部 2工作日 3非工作日
            if body.get("work_day") == "2":
                if ChineseCalendar(create_time[:10]).is_workday() and data[
                    "p"]:
                    p_slots[create_time[11:19]].append(
                        data["p"])
            elif body.get("work_day") == "3":
                if not ChineseCalendar(
                        create_time[:10]).is_workday() and data["p"]:
                    p_slots[create_time[11:19]].append(
                        data["p"])
            else:
                if data["p"]:
                    p_slots[create_time[11:19]].append(data["p"])
        for index, value in p_slots.items():
            p_slots[index] = sum(value) / len(value) if value else None
        # 负荷典型用电曲线 df_curve
        df_curve = pd.DataFrame(
            {"quarter_time": list(p_slots.keys()),
             "p": list(p_slots.values())},
            columns=["quarter_time", "p"])
        df_curve.loc[:, "quarter_time"] = pd.to_datetime(
            df_curve.loc[:, "quarter_time"])
        if elec_prices.get("price_s") and section_time_range.get("s"):
            peak_valley_price = elec_prices["price_s"] - elec_prices["price_v"]
            peak_flat_price = elec_prices["price_s"] - elec_prices["price_f"]
        else:
            peak_valley_price = elec_prices["price_p"] - elec_prices["price_v"]
            peak_flat_price = elec_prices["price_p"] - elec_prices["price_f"]
        log.info(f"cid:{body.get('cid')}, 峰谷价差:{peak_valley_price}, "
                 f"峰平价差:{peak_flat_price}")
        price = {
            "epc_price": body.get("epc_price"),  # epc单价，元/Wh
            "bank_interest": 0.085,  # 折现率
            "capacity_price": elec_prices["price_tc"],  # 容量电费
            "max_demand_price": elec_prices["price_md"],  # 需量电费
            # 峰谷价差，元/kWh 或者尖谷价差
            "peak_valley_price": peak_valley_price,
            # 峰平价差，元/kWh 或者尖平价差
            "peak_flat_price": peak_flat_price,
            "kwh_subsidy": body.get("kwh_subsidy"),  # 度电补贴
            # "section_s":{"time_range": "14:00-17:00;19:00-22:00"},
            "section_f": {"time_range": ";".join(section_time_range["f"])},
            "section_p": {"time_range": ";".join(section_time_range["p"])},
            "section_v": {"time_range": ";".join(section_time_range["v"])}
        }
        if section_time_range.get("s"):
            price["section_s"] = \
                {"time_range": ";".join(section_time_range.get("s"))}
        evaluate_year = 5000 // (int(body.get("rule")) *
                                 int(body.get("year_use_days")))
        ess_system = {
            "capacity": capacity,  # 工厂容量,kVA,
            "rule": body.get("rule"),  # 一充一放或两充两放
            "install_capacity": body.get("install_capacity"),  # kWh
            "bat_efficiency": 0.95,  # 电池效率
            "pcs_efficiency": 0.95,  # pcs转换效率
            "DOD": body.get("DOD"),  # 放电深度
            "decay_rate": body.get("decay_rate"),  # 衰减率
            # 年运维费用占静态投资额比例
            "maintenance_ratio_per_year": body.get(
                "maintenance_ratio_per_year"),
            "year_use_days": body.get("year_use_days"),  # 一年可利用时间
            "evaluate_year": evaluate_year,  # 评估年限
            "subsidy_year": body.get("subsidy_year"),  # 补贴年限
            # "invest_income_rate": (15, 12, 10, 8, 6), #投资收益率
            "loop_time": 5000  # 循环次数
        }
        
        obj = EssEvaluateTool(ess_system, price, max_demand_var, df_curve)
        obj.output()
        # 测算表
        etable = obj.evaluate_table
        evaluate_table = etable.where(etable.notnull(), None).round(2)
        evaluate_table["固定成本"] = evaluate_table["固定成本"].abs()
        # 下载
        if download:
            company = await select_cname_by_cid(body.get("cid"))
            table_name = f"{company['shortname']}_{body.get('start')}" \
                         f"_{body.get('end')}储能测算表"
            return await dataframe_excl_download(evaluate_table, table_name)
        curve = (obj.opt_curve.where(obj.opt_curve.notnull(), None)).round(
            2).reset_index()
        opt_curve = OptCurve(
            slot=curve["quarter_time"].values.tolist(),
            load_curve=curve["load_curve"].values.tolist(),
            bat_curve=curve["bat_curve"].values.tolist(),
            load_bat_curve=curve["load_bat_curve"].values.tolist(),
        )
        ess_compute_table = evaluate_table.to_dict("records")
        
        return EssEvaluateComputeResp(
            evaluate_table=opt_curve,
            ess_compute_table=ess_compute_table,
            invest_capacity=round(obj.invest_capacity, 2),
            static_period=round(obj.static_period, 2),
            pcs_capacity=round(obj.pcs_capacity, 2),
            month_average_dc_kwh=round(obj.month_average_dc_kwh, 2),
            month_dc_benefit=round(obj.month_dc_benefit, 2),
            download_url=url,
        )


# 电价设置
async def electrovalence_setting_service(cid, price_md, price_tc, std_cos,
                                         electrovalence):
    if std_cos not in (0.8, 0.85, 0.9):
        return success_res(code=4008, msg="功率因数错误")
    if price_md < 15 or price_md > 50:
        return success_res(code=4008, msg="容量单价范围应该在15-50之间")
    if price_tc < 15 or price_tc > 50:
        return success_res(code=4008, msg="需量单价范围应该在15-50之间")
    t = {}
    price_s, price_p, price_f, price_v = None, None, None, None
    for elec in electrovalence:
        if elec["name"] == "s":  # 尖
            price_s = elec.get("price", None)  # s可能没有
        if elec["name"] == "p":  # 峰
            price_p = elec["price"]
        if elec["name"] == "f":  # 平
            price_f = elec["price"]
        if elec["name"] == "v":  # 谷
            price_v = elec["price"]
        for slot in elec["slot"]:
            if slot[1] == "00:00":
                slot[1] = "24:00"
            start = slot[0].split(":")
            end = slot[1].split(":")
            if int(end[0]) < int(start[0]) or \
                    (int(end[0]) == int(start[0]) and int(end[1]) <= int(
                        start[1])):
                return success_res(code=400, msg="结束时间需要大于开始时间")
            fina = int(end[0]) + 1 if end[1] != "00" else int(end[0])
            for index, num in enumerate(range(int(start[0]), fina)):
                num = int(num)
                # 开始时间的分钟数不是0
                if index == 0:
                    for j in range(int(start[1]), 60, 15):
                        now_time = f"%02d:%02d" % (num, j)
                        if now_time in t.keys():
                            print(now_time)
                            print(t)
                            return success_res(code=400,
                                               msg="电价配置信息有误,存在重叠时间")
                        t[now_time] = elec["name"]
                # 结束时间的分钟数不是0
                elif index == (fina - 1) and end[1] != "00":
                    for j in range(0, int(end[1]), 15):
                        now_time = f"%02d:%02d" % (num, j)
                        if now_time in t.keys():
                            print(now_time)
                            print(t)
                            return success_res(code=400,
                                               msg="电价配置信息有误,存在重叠时间")
                        t[now_time] = elec["name"]
                else:
                    for j in range(0, 60, 15):
                        now_time = f"%02d:%02d" % (num, j)
                        if now_time in t.keys():
                            print(now_time)
                            print(t)
                            return success_res(code=400,
                                               msg="电价配置信息有误,存在重叠时间")
                        t[now_time] = elec["name"]
    if len(t.keys()) != 24 * 4:
        return success_res(code=400, msg="电价配置信息有误,缺少时间段")
    quarters = "".join([i[1] for i in sorted(t.items(), key=lambda x: x[0])])
    start_month = int(time.time())
    effect_time = datetime.date.today() + datetime.timedelta(days=1)
    effect_date = datetime.datetime(effect_time.year, effect_time.month,
                                    effect_time.day, 0, 0, 0).timestamp()
    # 找出cid 的所有inline_id
    inline_zdu_dic = await inline_zdu_all_by_cid(cid)
    # 1 设置电度电费  生效时间为明天凌晨
    for inline in inline_zdu_dic:
        inline_id = inline["inlid"]
        # 插入数据
        await insert_price_policy_data_dao(cid, inline_id, start_month,
                                           quarters, price_s, price_p, price_f,
                                           price_v, price_md, price_tc,
                                           effect_date)
        # 2 设置力调电价
        await inset_algorithm_power_factor_dao(inline_id, start_month, std_cos)
    return success_res(code=200, msg="设置电价成功")


async def electrovalence_service(cid):
    # 查找力调电费
    datas = await get_algorithm_power_factor_dao(cid)
    std_cos = float(datas.get("std_cos")) if datas.get("std_cos") else None
    # 查找电价
    elec_price = await get_elec_price_dao(cid)
    if not elec_price:
        log.error(f"该厂还未设置电价, cid:{cid}, table:price_policy")
        return success_res(code=4008, msg="该厂还未设置电价")
    section_time_range = get_section_time_range(elec_price["quarters"])
    electrovalence = []
    for section, value in section_time_range.items():
        electrovalence.append({
            "name": section,
            "price": elec_price.get(f"price_{section}"),
            "slot": [v.split("-") for v in value],
        })
    return ElectrovalenceResp(
        price_md=elec_price["price_md"],
        price_tc=elec_price["price_tc"],
        std_cos=std_cos,
        electrovalence=electrovalence
    )


def get_section_time_range(quarters):
    # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvffffffffppppssssffffffffppppssssssssppppppppffffffffffffffffffff
    # 转化成 {'v': '00:00-08:00', 's': '11:00-12:00;15:00-17:00',
    # 'p': '10:00-11:00;14:00-15:00;17:00-19:00',
    # 'f': '08:00-10:00;12:00-14:00;19:00-24:00'}
    d = {"v": [], "s": [], "p": [], "f": []}
    last_i, last_t = "", ""
    for index, i in enumerate(quarters):
        num = index % 4
        q = index // 4
        t = "%02d:%02d" % (q, num * 15)
        if index == 0:
            last_i = i
            last_t = t
        elif last_i != i:
            d[i].append(f"{t}-{t}")
            last_i = i
            last_t = t
        if d[i]:
            if (num + 1) * 15 == 60:
                q += 1
                end = 0
            else:
                end = (num + 1) * 15
            end_t = "%02d:%02d" % (q, end)
            q = d[i][-1][:5]
            d[i].pop()
            d[i].append(f"{q}-{end_t}")
        else:
            d[i].append(f"{last_t}-{t}")
    return d


def get_section_time_slot(elecs):
    d = {"v": [], "s": [], "p": [], "f": []}
    for name, value in elecs.items():
        for slot in value:
            start, end = slot.split("-")
            start_h, start_m = [int(i) for i in start.split(":")]
            end_h, end_m = [int(i) for i in end.split(":")]
            if start_m != 0:
                start_h += 1
            if end_m != 0:
                end_h += 1
            for i in range(start_h, end_h):
                d[name].append("%02d:00" % i)
    return d
