import copy
from functools import reduce

from mongoengine.queryset.visitor import Q
from ip_media.models import EntityType


def judge_the_param_is_true(k, genre, flag=False):
    """
    返回参数是否符合要求
    :param k: 判断的参数
    :param genre: 判断的类型
    :param flag: 追加判断是否为空
    :return:
    """
    judge = k is not None and isinstance(k, genre)
    if flag:
        judge = k if k else ""
    return judge


def combination_params(area_params, entity_params, flag="$and"):
    """
    aggregate组合match条件
    :param area_params: 区域条件
    :param entity_params: 渠道条件
    :param flag: 全部时是逻辑且，黑名单时是逻辑或
    :return:
    """
    match_params = dict()
    if area_params and entity_params:
        match_params = {flag: [area_params, entity_params]}
    elif area_params:
        match_params = area_params
    elif entity_params:
        match_params = entity_params
    return match_params


# 加载满足条件的黑名单match参数
def loading_black_entity_params(entity, field, entity_type, solo):
    entity_params = dict()
    if len(entity):
        _entity = [1] + entity if 1 not in entity else entity
        entity_params = {
            "china_property.{}".format(field): {"$elemMatch": {"entity": 1}},
            "china_property.mask.{}".format(entity_type): 0,
            "china_property.blkd": {"$elemMatch": {"entity": {"$in": entity}, "type": entity_type}}
        }

    if judge_the_param_is_true(solo, bool):
        _params = {"solo": solo}
        if entity_params:
            entity_params["china_property.{}".format(field)]["$elemMatch"].update(_params)
    return entity_params


# 加载查询白名单和黑名单全部的match参数
def loading_all_entity_params(entity, field, solo):
    entity_params = dict()
    if len(entity):
        _entity = [1] + entity if 1 not in entity else entity
        entity_params = {
            "china_property.{}".format(field): {"$elemMatch": {"entity": {"$in": _entity}}}
        }
    if judge_the_param_is_true(solo, bool):
        _params = {"solo": solo}
        if entity_params:
            entity_params["china_property.{}".format(field)]["$elemMatch"].update(_params)
    return entity_params


def supplement_property_params(query_set, area, entity_type, entity, solo, _from):
    """
    :param query_set: 查询集
    :param area: 区域
    :param entity: 渠道
    :param entity_type: 渠道类型
    :param solo: 排他  独家(True) | 非独家(False) null
    :param _from 聚合表名
    :return:
    """
    aggregate_str = [{
        "$lookup": {
            "from": _from,
            "localField": 'china_property',
            "foreignField": '_id',
            "as": 'china_property'
        }},
        {"$unwind": {"path": '$china_property', "preserveNullAndEmptyArrays": True}},
        {"$match": ""},
        {"$project": {"_id": 1}},
    ]
    code, res_query_id = 0, list()
    if judge_the_param_is_true(solo, bool) and (not len(area)) and (not len(entity)):
        _params = {"solo": solo}
        aggregate_str[2]["$match"] = {"$or": [
            {"china_property.area": {"$elemMatch": _params}},
            {"china_property.plat": {"$elemMatch": _params}},
            {"china_property.iptv": {"$elemMatch": _params}},
            {"china_property.ott": {"$elemMatch": _params}},
            {"china_property.sott": {"$elemMatch": _params}},
            {"china_property.dtv": {"$elemMatch": _params}},
            {"china_property.tv": {"$elemMatch": _params}},
            {"china_property.audio": {"$elemMatch": _params}},
        ]}
        _query_set = list(query_set.aggregate(aggregate_str))
        res_query_id = [qs["_id"] for qs in _query_set]
        code += 1
    elif len(area) or len(entity):
        area_all_match, area_black_match = dict(), dict()
        entity_all_match, entity_black_match = dict(), dict()
        if len(area):
            area_all_match = loading_all_entity_params(area, "area", solo)
            area_black_match = loading_black_entity_params(area, "area", "REGION", solo)
        if len(entity):
            field = EntityType.entity_property_filed_map()[entity_type]
            entity_all_match = loading_all_entity_params(entity, field, solo)
            entity_black_match = loading_black_entity_params(entity, field, entity_type, solo)
        all_match = combination_params(area_all_match, entity_all_match)
        black_match = combination_params(area_black_match, entity_black_match, flag="$or")
        aggregate_str[2]["$match"] = all_match
        all_query_set = list(query_set.aggregate(aggregate_str))         # 满足条件不分黑名单和白名单进行筛选
        aggregate_str[2]["$match"] = black_match                         # 满足条件的黑名单情况
        black_query_set = list(query_set.aggregate(aggregate_str))
        all_id = [qs["_id"] for qs in all_query_set]
        black_id = [qs["_id"] for qs in black_query_set]
        res_query_id = list(set(all_id) - set(black_id))                # 从全部中剔除黑名单
        code += 1
    return code, res_query_id
