import time
from datetime import datetime, timedelta

from aioredis import RedisError
from elasticsearch import ElasticsearchException
from pymysql import MySQLError

from pot_libs.logger import log
from pot_libs.sanic_api import summary
from unify_api.modules.common.components.common_cps import CidReq

from unify_api.modules.home_page.components.count_info_cps import (
    CountInfoResp,
    CountInfoReq,
    EconomicPowerCountResp, CountItemNew,
    CountItem, RiskCostReq, RiskCostResp, EconomicPowerCountNewResp
)
from unify_api.modules.home_page.components.count_info_proxy_cps import \
    CountInfoProxyResp, IycResp, IycmResp, RtrResp, CmResp, ApcResp, AsiResp, \
    HsiResp, AiiResp
from unify_api.modules.home_page.procedures.count_info_pds import (
    get_max_aiao_of_filed, normal_rate_of_location,
    other_info,
    power_count_info,
    electric_use_info,
    power_charge_price,
    cal_power_factor,
    optimization_count_info, optimization_count_info_new
)
from unify_api.modules.home_page.service.count_info_service import \
    post_zd_info_factory_service, risk_cost_service, info_yang_chen_service, \
    info_yang_chen_map_service, rank_type_ranking_service, \
    condition_monitor_service, alarm_price_costtl_service, \
    alarm_safe_index_service, all_index_info_service


@summary("获取首页统计信息")
async def post_count_info(request, body: CountInfoReq) -> CountInfoResp:
    # 1. 获取company_id
    company_id = body.cid
    # now_tt = time.time()
    # start_dt = datetime.now() - timedelta(30)
    # start_tt = datetime_to_timestamp(
    #     datetime(start_dt.year, start_dt.month, start_dt.day))
    now_tt = str(datetime.now())
    start_tt = str(datetime.now() - timedelta(30))
    try:

        max_residual_current = await get_max_aiao_of_filed(company_id,
                                                           start_tt, now_tt,
                                                           "residual_current")
        max_temperature = await get_max_aiao_of_filed(company_id, start_tt,
                                                      now_tt, "temperature")

        # 温度和漏电流实时达标率
        # temperature_qr, residual_current_qr = await normal_rate_of_location(
        #     company_id)
        temperature_qr, residual_current_qr = await \
            normal_rate_of_location(company_id)

        # 今日报警数和累计安全运行天数
        # today_alarm_count, safe_run_days, alarm_count = await other_info(
        #     company_id)
        today_alarm_count, safe_run_days, alarm_count = await other_info(
            company_id)

        # 实时负荷和近30日最高负荷
        current_load, max_30d_load = await power_count_info(company_id)

        # 用电安全指数, 报警分, 近30天报警1,2,3级数目
        # electric_info = await electric_use_info(company_id)
        electric_info = await electric_use_info(company_id)

        # 昨日平均电价, 上月平均电价
        yestoday_price, last_month_price = await power_charge_price(
            company_id)

        # 实时功率因数, 上月功率因数
        # cos_ttl, last_month_cos = await power_factor(company_id)
        cos_ttl, last_month_cos = await cal_power_factor(company_id)

    # 其实异常捕获这个东西最好是在框架内部做一次就够了
    except (ElasticsearchException, MySQLError, RedisError) as e:
        log.exception(e)
        return CountInfoResp().db_error()
    except Exception as e:
        log.exception(e)
        return CountInfoResp().server_error()

    return CountInfoResp(
        max_residual_current=max_residual_current,
        max_temperature=max_temperature,
        temperature_qr=temperature_qr,
        residual_current_qr=residual_current_qr,
        today_alarm_count=today_alarm_count,
        safe_run_days=safe_run_days,
        current_load=current_load,
        max_30d_load=max_30d_load,
        electric_info=electric_info,
        yestoday_price=yestoday_price,
        last_month_price=last_month_price,
        cos_ttl=cos_ttl,
        last_month_cos=last_month_cos,
    )


@summary("获取首页用电经济指数")
async def post_electric_economic_index(request,
                                       body: CountInfoReq) -> EconomicPowerCountResp:
    cid = int(body.cid)

    count_info_map = await optimization_count_info(cid)

    power_factor_info = count_info_map["power_factor"]
    pcvf_info = count_info_map["pcvf"]
    power_save_info = count_info_map["power_save"]
    md_space_info = count_info_map["md_space"]
    save_percent = count_info_map["save_percent"]
    avg_price = count_info_map["avg_price"]
    md_space_p = count_info_map["md_space_p"]
    mean_load_factor = count_info_map["mean_load_factor"]
    max_save_charge = sum(
        [
            i["save_charge"] if i["save_charge"] else 0
            for i in
            [power_factor_info, pcvf_info, power_save_info, md_space_info]
        ]
    )
    if save_percent == "":
        economic_power_index = 100
    elif save_percent >= 0 and save_percent < 0.005:
        economic_power_index = -2000 * save_percent + 100
    elif save_percent >= 0.005 and save_percent < 0.02:
        economic_power_index = -1000 * save_percent + 95
    elif save_percent >= 0.02 and save_percent < 0.05:
        economic_power_index = -500 * save_percent + 85
    elif save_percent >= 0.05 and save_percent < 0.1:
        economic_power_index = -1200 * save_percent + 120
    else:
        economic_power_index = 0

    return EconomicPowerCountResp(
        power_factor=CountItem(
            index=power_factor_info["kpi_x"],
            save_charge=power_factor_info["save_charge"],
            desc=power_factor_info["desc"],
        ),
        pcvf=CountItem(
            index=pcvf_info["kpi_x"], save_charge=pcvf_info["save_charge"],
            desc=pcvf_info["desc"],
        ),
        power_save=CountItem(
            index=power_save_info["kpi_x"],
            save_charge=power_save_info["save_charge"],
            desc=power_save_info["desc"],
        ),
        md_space=CountItem(
            index=md_space_info["kpi_x"],
            save_charge=md_space_info["save_charge"],
            desc=md_space_info["desc"],
        ),
        avg_price=avg_price,
        save_percent=save_percent,
        economic_power_index=economic_power_index,
        md_space_p=md_space_p,
        mean_load_factor=mean_load_factor,
        max_save_charge=max_save_charge,
    )


@summary("工厂版首页统计信息-智电U")
async def post_zd_info_factory(req, body: CountInfoReq) -> CountInfoProxyResp:
    # 1. 获取cid
    cid = body.cid
    cid_list = [cid]
    total_monitor, safe_operation_days, total_power, total_alarm, co2 = \
        await post_zd_info_factory_service(cid_list)
    return CountInfoProxyResp(
        total_monitor=total_monitor,
        safe_operation_days=safe_operation_days,
        total_power=total_power,
        total_alarm=total_alarm,
        co2=co2
    )


@summary("工厂版运行统计-风险成本-智电U")
async def post_risk_cost(req, body: RiskCostReq) -> RiskCostResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    risk_list, cost_list = await risk_cost_service(cid)
    return RiskCostResp(risk_data=risk_list, cost_data=cost_list)


@summary("工厂版首页统计信息-扬尘")
async def post_info_yang_chen(req, body: CountInfoReq) -> IycResp:
    # 1. 获取cid
    cid = body.cid
    # return await info_yang_chen_service(cid)
    return IycResp(total_point=20, air_quality=10, safe_operation_days=11,
                   total_water=132.80, total_kwh=0)  # 扬尘接口,返回空数据


@summary("工厂版首页地图信息-扬尘")
async def post_info_yang_chen_map(req, body: CountInfoReq) -> IycmResp:
    # 1. 获取cid
    cid = body.cid
    # return await info_yang_chen_map_service(cid)
    return IycmResp(safety_index=89, today_alarm=5, total_max_pm25=27.12,
                    center_address=[], range_address=[])


@summary("获取首页用电经济指数")
async def post_electric_economic_index_new(request,
                                           body: CountInfoReq) -> EconomicPowerCountNewResp:
    cid = int(body.cid)

    count_info_map = await optimization_count_info_new(cid)

    power_factor_info = count_info_map["power_factor"]
    pcvf_info = count_info_map["pcvf"]
    power_save_info = count_info_map["power_save"]
    md_space_info = count_info_map["md_space"]
    avg_price = count_info_map["avg_price"]
    md_space_p = count_info_map["md_space_p"]
    mean_load_factor = count_info_map["mean_load_factor"]
    save_percent = count_info_map["save_percent"]
    max_save_charge = sum(
        [
            i["save_charge"] if i["save_charge"] else 0
            for i in
            [power_factor_info, pcvf_info, power_save_info, md_space_info]
        ]
    )
    if save_percent == "":
        economic_power_index = 100
    elif 0 <= save_percent < 0.005:
        economic_power_index = -2000 * save_percent + 100
    elif 0.005 <= save_percent < 0.02:
        economic_power_index = -1000 * save_percent + 95
    elif 0.02 <= save_percent < 0.05:
        economic_power_index = -500 * save_percent + 85
    elif 0.05 <= save_percent < 0.1:
        economic_power_index = -1200 * save_percent + 120
    else:
        economic_power_index = 0
    return EconomicPowerCountNewResp(
        power_factor=CountItemNew(
            index=power_factor_info["kpi_x"],
            save_charge=power_factor_info["save_charge"],
            desc=power_factor_info["desc"],
            space=power_factor_info["space"]
        ),
        pcvf=CountItemNew(
            index=pcvf_info["kpi_x"], save_charge=pcvf_info["save_charge"],
            desc=pcvf_info["desc"], space=pcvf_info["space"]
        ),
        power_save=CountItemNew(
            index=power_save_info["kpi_x"],
            save_charge=power_save_info["save_charge"],
            desc=power_save_info["desc"],
            space=power_save_info["space"]
        ),
        md_space=CountItemNew(
            index=md_space_info["kpi_x"],
            save_charge=md_space_info["save_charge"],
            desc=md_space_info["desc"],
            space=md_space_info["space"]
        ),
        avg_price=avg_price,
        save_percent=save_percent,
        economic_power_index=round(economic_power_index),
        md_space_p=md_space_p,
        mean_load_factor=mean_load_factor,
        max_save_charge=max_save_charge,
    )


@summary("首页报警统计-等级类型排名-智电U")
async def post_rank_type_ranking(req, body: CidReq) -> RtrResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    return await rank_type_ranking_service(cid)


@summary("首页状态监测-智电U")
async def post_condition_monitor(req, body: CidReq) -> CmResp:
    """最近5min报警"""
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    return await condition_monitor_service(cid)


@summary("首页-今日报警平均电价等-智电U")
async def post_alarm_price_costtl(req, body: CidReq) -> ApcResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    return await alarm_price_costtl_service(cid)


@summary("首页-用电安全指数等")
async def post_alarm_safe_index(req, body: CidReq) -> AsiResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    return await alarm_safe_index_service(cid)


@summary("首页-健康指数等")
async def post_health_status_index(req, body: CidReq) -> HsiResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    # return await health_status_index_service(cid)


@summary("首页-全部指数")
async def post_all_index_info(req, body: CidReq) -> AiiResp:
    # 1. 获取参数
    cid = body.cid
    # 2. 调service获取数据
    return await all_index_info_service(cid)