# -*- coding:utf-8 -*-
import json
from unify_api import constants
from unify_api.modules.alarm_manager.components.list_alarm import \
    ListAlarmResponse, Alarm
from unify_api.modules.alarm_manager.dao.alarm_setting_dao import \
    company_extend_dao, get_list_alarm_dao, get_total_list_alarm_dao
from unify_api.modules.alarm_manager.dao.list_alarm_dao import \
    wx_list_alarm_dao, \
    wx_list_alarm_zdu_dao, list_alarm_zdu_dao, new_list_alarm_dao
from unify_api.modules.common.procedures.cids import get_cid_info
from unify_api.modules.common.procedures.points import points_by_storeys
from unify_api.modules.electric.dao.electric_dao import \
    monitor_point_join_points
from unify_api.utils import time_format
from unify_api.modules.common.dao.common_dao import (
    load_user_lang, load_monitor_names
)
from unify_api.modules.common.procedures.multi_lang import (
    load_event_msg, load_phase_line, load_e_type_name
)


async def new_list_alarm_service(cid, storeys, offset, page_size, start, end,
                                 importance, points, product):
    """报警信息分页列表"""
    # 1.根据storeys获取points信息
    point_list = await points_by_storeys(cid, storeys)
    if not point_list:
        return ListAlarmResponse(total=0, rows=[])
    # point_id和storey对应关系
    point_storey_map = {info["point_id"]: info for info in point_list}
    if not points:
        # 获取point_id列表
        points = [i.get("point_id") for i in point_list]
        point_ids = [{"point_id": i.get("point_id"),
                      "point_name": i.get("room_name")} for i in point_list]
    else:
        point_ids = [
            {"point_id": i.get("point_id"),
             "point_name": i.get("room_name")}
            for i in point_list if i["point_id"] in points]
    # 2. 查询结果
    total, results = await new_list_alarm_dao(cid, points, start, end,
                                              importance,
                                              offset, page_size)
    if not results:
        return ListAlarmResponse(total=0, rows=[])
    # 2. 构建返回数据
    cid_info_map = await get_cid_info(all=True)
    # 3.增加sid返回字段, sdu龙岗客户需求
    monitor_point_list = await monitor_point_join_points(points)
    point_sid_map = {i["pid"]: i["sid"] for i in monitor_point_list}
    point_mtid_map = {i["pid"]: i["mtid"] for i in monitor_point_list}
    rows = []
    for res in results:
        es_id = res.get("id")
        type = res.get("event_type")
        mode = res.get("event_mode")
        type_str = constants.SDU_EVENT_TYPE_MAP.get(type, type)
        point_id = res.get("pid")
        location_id = res.get("lid")
        date_time = res.get("event_datetime")
        dt = time_format.convert_to_dt(date_time)
        date_time = time_format.convert_dt_to_timestr(dt)
        event_duration = res.get("event_duration")
        if point_id and mode == "scope":
            url = "/scope_details?doc_id=%s" % es_id
            redirect_type = "scope"
        elif location_id and type in constants.TEMP_SCOPE_URL_TYPE:
            url = "/temp_trend?doc_id=%s" % es_id
            redirect_type = "temp_trend"
        else:
            url = None
            redirect_type = ""
        cid = int(res.get("cid")) if res.get("cid") else res.get("cid")

        storey_name = point_storey_map[point_id]["storey_name"]
        room_name = point_storey_map[point_id]["room_name"]
        alarm = Alarm(
            name=res.get("name"),
            importance=res.get("importance"),
            date_time=date_time,
            type=type,
            type_name=type_str,
            description=res.get("message"),
            redirect_type=redirect_type,
            es_id=es_id,
            url=url,
            event_duration=event_duration,
            company_name=cid_info_map.get(cid, {}).get("fullname", ""),
            point_id=point_id,
            storey_name=storey_name,
            room_name=room_name,
            storey_room_name=storey_name + room_name,
            sid=point_sid_map.get(point_id),
            mtid=point_mtid_map.get(point_id)
        )
        rows.append(alarm)
    return ListAlarmResponse(total=total, rows=rows, point_ids=point_ids)


async def wx_list_alarm_service(cids, product, start, end):
    """小程序消息列表"""
    total, results = await wx_list_alarm_dao(cids, start, end)
    if not results:
        return ListAlarmResponse(total=0, rows=[])

    cid_info_map = await get_cid_info(all=True)
    rows = []
    for res in results:
        es_id = res.get("id")
        type = res.get("event_type")
        type_str = constants.SDU_EVENT_TYPE_MAP.get(type, type)
        point_id = res.get("pid")
        date_time = res.get("event_datetime")
        dt = time_format.convert_to_dt(date_time)
        date_time = time_format.convert_dt_to_timestr(dt)
        event_duration = res.get("event_duration")
        cid = int(res.get("cid")) if res.get("cid") else res.get("cid")
        alarm = Alarm(
            point_id=point_id,
            name=res.get("name"),
            importance=res.get("importance"),
            date_time=date_time,
            type=type,
            type_name=type_str,
            description=res.get("message"),
            es_id=es_id,
            event_duration=event_duration,
            company_name=cid_info_map.get(cid, {}).get("fullname", ""),
        )
        rows.append(alarm)
    return ListAlarmResponse(total=total, rows=rows)


async def list_alarm_zdu_service(cid, point_list, page_num, page_size, start,
                                 end, importance, event_type):
    """报警信息分页列表"""
    if not point_list or not event_type or not importance:
        return ListAlarmResponse(total=0, rows=[])

    results = await list_alarm_zdu_dao(cid, point_list, start, end, importance,
                                       event_type)
    real_total = len(results)
    results = results[(page_num - 1) * page_size, page_num * page_size]
    # 2. 获取工厂, 报警type对应的描述信息
    event_dic = await company_extend_dao(cid)
    event_dic_map = {event["key"]: event for event in event_dic}
    # 3. 构建返回数据
    rows = []
    for res in results:
        es_id = res.get("id")
        type = res.get("event_type")
        mode = res.get("event_mode")
        type_str = constants.EVENT_TYPE_MAP.get(type, type)
        point_id = res.get("pid")
        location_id = res.get("lid")
        date_time = res.get("event_datetime")
        dt = time_format.convert_to_dt(date_time)
        date_time = time_format.convert_dt_to_timestr(dt)
        event_duration = res.get("event_duration")
        if point_id and mode == "scope":
            url = "/scope_details?doc_id=%s" % es_id
            redirect_type = "scope"
        elif location_id and type in constants.TEMP_SCOPE_URL_TYPE:
            url = "/temp_trend?doc_id=%s" % es_id
            redirect_type = "temp_trend"
        else:
            url = None
            redirect_type = ""

        alarm = Alarm(
            name=res.get("name"),
            importance=res.get("importance"),
            date_time=date_time,
            type=type,
            type_name=type_str,
            description=event_dic_map[type]["value"],
            redirect_type=redirect_type,
            es_id=es_id,
            url=url,
            event_duration=event_duration,
            point_id=point_id,
            content=res.get("message"),
        )
        rows.append(alarm)

    total = real_total if real_total < constants.ES_TOTAL_LIMIT \
        else constants.ES_TOTAL_LIMIT
    return ListAlarmResponse(total=total, rows=rows)


async def wx_list_alarm_zdu_service(cid, point_list, start, end):
    """小程序消息列表-智电u"""
    # 1. es查询结果
    results = await wx_list_alarm_zdu_dao(cid, point_list, start, end)
    if not results:
        return ListAlarmResponse(total=0, rows=[])

    # 2. 获取工厂, 报警type对应的描述信息
    event_dic = await company_extend_dao(cid)
    event_dic_map = {event["key"]: event for event in event_dic}
    # 3. 构建返回数据
    rows = []
    for res in results:
        es_id = res.get("id")
        type = res.get("event_type")
        mode = res.get("event_mode")
        type_str = constants.EVENT_TYPE_MAP.get(type, type)
        point_id = res.get("pid")
        location_id = res.get("lid")
        date_time = res.get("event_datetime")
        dt = time_format.convert_to_dt(date_time)
        date_time = time_format.convert_dt_to_timestr(dt)
        event_duration = res.get("event_duration")
        if point_id and mode == "scope":
            url = "/scope_details?doc_id=%s" % es_id
            redirect_type = "scope"
        elif location_id and type in constants.TEMP_SCOPE_URL_TYPE:
            url = "/temp_trend?doc_id=%s" % es_id
            redirect_type = "temp_trend"
        else:
            url = None
            redirect_type = ""

        alarm = Alarm(
            name=res.get("name"),
            importance=res.get("importance"),
            date_time=date_time,
            type=type,
            type_name=type_str,
            description=event_dic_map[type]["value"],
            redirect_type=redirect_type,
            es_id=es_id,
            url=url,
            event_duration=event_duration,
            point_id=point_id,
            content=res.get("message"),
        )
        rows.append(alarm)

    # total小程序不分页, 返回了但是不用
    return ListAlarmResponse(total=len(results), rows=rows)


async def pack_alarm_records(records, pid, lang):
    if not records:
        return []

    alarm_recs, mtr_names = [], {}
    if lang != "zh_CN":
        mtids = [r["mtid"] for r in records]
        mtr_names = await load_monitor_names(mtids, lang)

    for r in records:
        event_type = r.get("event_type")
        event_duration = r.get("event_duration")
        type_str = load_e_type_name(event_type, lang)
        es_id = r.get("id")
        if pid and r.get("event_mode") == "scope":
            url, redirect_type = f"/scope_details?doc_id={es_id}", "scope"
        elif r.get("lid") and event_type in constants.TEMP_SCOPE_URL_TYPE:
            url, redirect_type = f"/temp_trend?doc_id={es_id}", "temp_trend"
        else:
            url, redirect_type = None, ""

        mtr_name = r.get("name")
        if lang == "zh_CN":
            event_msg = r.get("message")
        else:
            event_param = r["event_param"]
            if event_param:
                event_param = json.loads(r["event_param"])
            event_msg = load_event_msg(event_type, event_param, lang)
            if not event_msg:
                event_msg = r.get("message")

            phase_line = load_phase_line(mtr_name, lang)
            name = mtr_names[r["mtid"]]
            mtr_name = f"{name}{phase_line}" if phase_line else name

        alarm = Alarm(
            name=mtr_name,
            importance=r.get("importance"),
            date_time=str(r.get("event_datetime")),
            type=event_type,
            type_name=type_str,
            description=event_msg,
            redirect_type=redirect_type,
            es_id=es_id,
            url=url,
            event_duration=round(event_duration)
            if isinstance(event_duration, float) else event_duration,
            company_name=r.get("fullname") or '',
        )
        alarm_recs.append(alarm)

    return alarm_recs


async def list_alarm_service(cid, user_id, point_id, start, end, importance,
                             page_size, page_num, alarm_type):
    conds = ["event_mode!='scope'"]
    if point_id:
        conds.append(f"pid={point_id}")
    else:
        if not isinstance(cid, list):
            cid = [cid]
        cid_where = str(tuple(cid)).replace(",)", ")")
        conds.append(f"cid in {cid_where}")

    if start and end:
        conds.append(f"event_datetime BETWEEN '{start}' and '{end}'")

    if importance:
        if len(importance) == 1:
            conds.append(f"importance={importance[0]}")
        else:
            conds.append(f"importance in {str(tuple(importance)).strip(',')}")
    else:
        conds.append("importance in (1, 2, 3)")

    if alarm_type:
        if len(alarm_type) == 1:
            conds.append(f"event_type='{alarm_type[0]}'")
        else:
            conds.append(f"event_type in {str(tuple(alarm_type)).strip(',')}")

    total = await get_total_list_alarm_dao(" AND ".join(conds))

    conds_str = " AND ".join(["point_1min_event." + i for i in conds])
    alarm_lst = await get_list_alarm_dao(conds_str, page_size, page_num)
    if not alarm_lst:
        return ListAlarmResponse(total=0, rows=[])

    lang = await load_user_lang(user_id)
    alarm_records = await pack_alarm_records(alarm_lst, point_id, lang)
    return ListAlarmResponse(total=total, rows=alarm_records)
