# -*- coding:utf-8 -*-
#
# Author:jing
# Date: 2020/7/9
import random
from datetime import datetime, timedelta

from pot_libs.sanic_api import summary, description, examples
from pot_libs.es_util.es_utils import EsUtil
from pot_libs.logger import log
from pot_libs.es_util.es_query import EsQuery
from pot_libs.utils.exc_util import DBException, BusinessException
from unify_api.constants import Product
from unify_api.modules.alarm_manager.components.alarm_static_cps import NlaReq, \
    WlaReq, LazReq
from unify_api.modules.alarm_manager.service.list_alarm_service import \
    new_list_alarm_service, wx_list_alarm_service, list_alarm_zdu_service, \
    wx_list_alarm_zdu_service, list_alarm_service_new15
from unify_api.modules.common.procedures.cids import get_cid_info, get_cids, \
    get_proxy_cids
from unify_api.utils import time_format
from unify_api import constants
from pot_libs.common.components.query import PageRequest, Equal, Range, Filter, \
    InGroup
from unify_api.modules.alarm_manager.components.list_alarm import (
    ListAlarmResponse, ListAlarmReq,
    Alarm,
    list_alarm_example, WlazReq,
)


@summary("返回报警信息列表")
@description("筛选字段：监测点")
# @examples(list_alarm_example)
async def post_list_alarm(req, body: PageRequest) -> ListAlarmResponse:
    cid = req.json.get("cid")
    page_size = body.page_size
    page_num = body.page_num
    start, end = '', ''
    point_id = None
    alarm_type = []
    importance = []
    if body.filter.ranges:
        _range = body.filter.ranges[0]
        _, start, end = _range.field, _range.start, _range.end
    if body.filter.equals:
        for equal in body.filter.equals:
            if equal.field == 'cid':
                cid = equal.value
            elif equal.field == 'point_id':
                point_id = equal.value
    if body.filter.in_groups:
        for in_group in body.filter.in_groups:
            if in_group.field == 'type':
                alarm_type = in_group.group
            elif in_group.field == 'importance':
                importance = in_group.group
    return await list_alarm_service_new15(cid, point_id, start, end,
                                          importance, page_size, page_num,
                                          alarm_type)


@summary("上面的备份")
@description("筛选字段：监测点")
@examples(list_alarm_example)
async def post_list_alarm_bak(req, body: PageRequest) -> ListAlarmResponse:
    # 将"2020-05-02 17:32:31”格式的时间转化为"2020-05-02T17:32:31+08:00"
    # 小程序首页展示报警信息列表最新40条，不需要传时间
    if body.filter.ranges:
        _range = body.filter.ranges[0]
        field, start, end = _range.field, _range.start, _range.end
        start_dt = time_format.convert_to_dt(start)
        start_str = time_format.convert_dt_to_str(start_dt, date_type="tz")
        end_dt = time_format.convert_to_dt(end)
        end_str = time_format.convert_dt_to_str(end_dt, date_type="tz")
        _range = Range(field=field, start=start_str, end=end_str)
        ranges = [_range]
    else:
        ranges = []

    # TODO:当没有选择监测点的时候，需要从req取cid，作为筛选条件
    if req.json.get("cid"):
        cid = req.json["cid"]
        equal = Equal(field="cid", value=cid)
        body.filter.equals.append(equal)

    if req.json.get("product") == Product.AndianUManage.value:
        proxy_id = req.json.get("proxy_id")
        product = req.json.get("product")
        user_id = req.ctx.user_id
        req_cids = req.json.get("cids")

        # cids = await get_cids(user_id, product)
        cids = await get_proxy_cids(user_id, product, proxy_id)
        if req_cids:
            if any(i for i in req_cids if i not in cids):
                raise BusinessException(
                    message=f"你没有工厂{set(req_cids) - set(cids)}没有权限")
            in_group = InGroup(field="cid", group=req_cids)
        else:
            in_group = InGroup(field="cid", group=cids)
        body.filter.in_groups.append(in_group)

    if req.json.get("product") in [Product.RecognitionElectric.value,
                                   Product.IntelligentU.value]:
        req_cid = req.json.get("cid")
        if not req_cid:
            product = req.json.get("product")
            user_id = req.ctx.user_id
            cids = await get_cids(user_id, product)
        else:
            cids = [req_cid]
            in_group = InGroup(field="cid", group=cids)
            body.filter.in_groups.append(in_group)

    filter = Filter(
        equals=body.filter.equals,
        ranges=ranges,
        in_groups=body.filter.in_groups,
        keywords=body.filter.keywords,
    )

    # 重新封装PageRequest
    page_request = PageRequest(
        page_size=body.page_size, page_num=body.page_num, sort=body.sort,
        filter=filter
    )
    query_body = EsQuery().query(page_request)
    if not query_body.get("query"):
        query = {"bool": {"must_not": [{"terms": {"mode.keyword": ["scope"]}}]}}
        query_body["query"] = query
    else:
        must_not = [{"terms": {"mode.keyword": ["scope"]}}]
        query_body["query"]["bool"]["must_not"] = must_not
    index = "poweriot_point_1min_event"
    log.info(f"index:{index}--query_body:{query_body}")
    async with EsUtil() as es:
        es_results = await es.search_origin(body=query_body, index=index)
        if not es_results:
            log.warning(
                "Can not find data on es(index: %s): %s" % (index, query_body))
            raise DBException

        cid_info_map = await get_cid_info(all=True)
        rows = []
        for info in es_results["hits"]["hits"]:
            es_id = info["_id"]
            source = info["_source"]
            type = source.get("type")
            mode = source.get("mode")
            type_str = constants.EVENT_TYPE_MAP.get(type, type)
            point_id = source.get("point_id")
            location_id = source.get("location_id")
            date_time = source.get("datetime")
            dt = time_format.convert_to_dt(date_time)
            date_time = time_format.convert_dt_to_timestr(dt)
            event_duration = source.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(source.get("cid")) if source.get("cid") else source.get(
                "cid")
            alarm = Alarm(
                name=source.get("name"),
                importance=source.get("importance"),
                date_time=date_time,
                type=type,
                type_name=type_str,
                description=source.get("message"),
                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=cid_info_map.get(cid, {}).get("fullname", ""),
            )
            rows.append(alarm)

        real_total = es_results["hits"]["total"]
        total = real_total if real_total < constants.ES_TOTAL_LIMIT else constants.ES_TOTAL_LIMIT
        return ListAlarmResponse(total=total, rows=rows)


@summary("报警记录-列表分页")
async def post_new_list_alarm(req, body: NlaReq) -> ListAlarmResponse:
    # 1. 获取参数
    cid = body.cid
    storeys = body.storeys
    page_num = body.page_num
    page_size = body.page_size
    start = body.start
    end = body.end
    product = body.product
    importance = body.importance
    point_ids = body.point_ids
    # 2. 调用service
    return await new_list_alarm_service(cid, storeys,
                                        (page_num - 1) * page_size, page_size,
                                        start, end, importance, point_ids,
                                        product)



@summary("小程序消息列表")
async def post_wx_list_alarm(req, body: WlaReq) -> ListAlarmResponse:
    # 1. 获取参数
    cids = body.cids
    product = body.product
    # 如果没有传start和end, 取最新40条, 传了start/end取范围内最新40条
    start = body.start
    end = body.end
    # 2. 调用service
    return await wx_list_alarm_service(cids, product, start, end)


@summary("报警记录-列表分页-智电u")
async def post_list_alarm_zdu(req, body: LazReq) -> ListAlarmResponse:
    # 1. 获取参数
    cid = body.cid
    point_list = body.point_list
    page_num = body.page_num
    page_size = body.page_size
    start = body.start
    end = body.end
    importance = body.importance
    event_type = body.event_type
    # 2. 调用service
    return await list_alarm_zdu_service(cid, point_list, page_num, page_size,
                                        start, end, importance, event_type)


@summary("小程序消息列表-智电u")
async def post_wx_list_alarm_zdu(req, body: WlazReq) -> ListAlarmResponse:
    # 1. 获取参数
    cid = body.cid
    point_list = body.point_list
    # 如果没有传start和end, 取最新100条, 传了start/end取范围内最新100条
    start = body.start
    end = body.end
    # 2. 调用service
    return await wx_list_alarm_zdu_service(cid, point_list, start, end)
