#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json

from django.db.models import Q

from api.models.face.ai_target import AiTarget

from gm_types.gaia import (
    SKIN_CONF_ACNE_TYPE,
    SKIN_CONF_CHEEK_TYPE,
    SKIN_CONF_CHIN_TYPE,
    SKIN_CONF_COLOR_TEMP_TYPE,
    SKIN_CONF_HEITOU_TYPE,
    SKIN_CONF_MAOKONG_TYPE,
    SKIN_CONF_PIGMENTAL_TYPE,
    SKIN_CONF_SMOOTH_TYPE,
    SKIN_CONF_STRUCT_TYPE,
    SKIN_CONF_T_ZONE_TYPE,
    SKIN_CONF_VASCULAR_TYPE,
    SKIN_CONF_ACT_WRINKLE_TYPE,
    SKIN_CONF_EYE_BAG_TYPE,
    AI_TARGET_PART,
    SCAN_TYPE,
    USER_GENDER,
    KS_SKIN_ALL_TYPE,
    KS_DARK_CIRCLE_TYPE,
    KS_SKIN_TYPE,
    KS_BLACKHEAD_TYPE,
    KS_PORES_FOREHEAD_TYPE,
    KS_PORES_LEFT_CHEEK_TYPE,
    KS_PORES_RIGHT_CHEEK_TYPE,
    KS_PORES_JAW_TYPE,
    KS_PORE_TYPE,
    KS_ACNE_TYPE,
    KS_EYE_POUCH_TYPE,
    KS_NASOLABIAL_FOLD_TYPE,
    KS_SKIN_COLOR,
    KS_SKIN_SPOT_TYPE,
    KS_MOLE_TYPE,
    KS_FOREHEAD_WRINKLE_YPE,
    KS_GLABELLA_WRINKLE_YPE,
    KS_CROWS_FEET_YPE,
    KS_EYE_FINELINES_YPE,
)

from api.models.face import (
    Acne,
    Heitou,
    HeiYanQuan,
    SkinAge,
    SkinOil,
    SkinColor,
    Smoothlevel,
    ActWrinkle,
    EyeBag,
    SkinType,
    BlackheadPore,
)
from polymer.models import PolymerSurgery
from rpc.tool.dict_mixin import to_dict


class SkinResultService(object):

    @staticmethod
    def get_objs_by_query_and_order(model_set, query, order_by=[]):
        """
        获取 query_set对象
        :param model_set:
        :param query:
        :param order_by:
        :return:
        """
        _queryset = model_set.objects.filter(
            query).order_by(*order_by)

        return _queryset

    @staticmethod
    def format_skin_result(obj):
        _data = {}
        if not obj:
            return _data

        _data = {
            'id': obj.id,
            'total_score': obj.total_score,

            'skin_radar': obj.skin_radar,
            'dark_circle': obj.dark_circle,

            'gender': 'female' if obj.gender == USER_GENDER.FEMALE else 'male',
            'skin_age': obj.skin_age,
            'skin_color_level': obj.skin_color_level,
            'skin_color_desc': obj.skin_color_desc,
            'skin_color_temperature': obj.skin_color_temperature,
            'oil_level': obj.oil_level,
            'blackhead_number': obj.blackhead_number,
            'blackhead_severity': obj.blackhead_severity,
            'tzone_oil_shine': obj.tzone_oil_shine,
            'cheek_oil_shine': obj.cheek_oil_shine,
            'chin_oil_shine': obj.chin_oil_shine,
            'pore_severity': obj.pore_severity,
            'coarseness': obj.coarseness,

            'acne': obj.acne,
            'acne_severity': obj.acne_severity,
            'acne_desc': obj.acne_desc,

            'short_oil_level_advice': obj.short_oil_level_advice,
            'short_coarseness_advice': obj.short_coarseness_advice,
            'short_blackhead_advice': obj.short_blackhead_advice,
            'short_acne_advice': obj.short_acne_advice,
            'short_dark_circle_advice': obj.short_dark_circle_advice,

            'image_url': obj.image_url,
            'device_id': obj.device_id,
            'user_id': obj.user_id,
            'created_time': obj.created_time.strftime("%Y-%m-%d %H:%M:%S"),
            'face_diagnose': json.loads(obj.face_diagnose) if obj.face_diagnose else {},
        }

        return _data

    @staticmethod
    def format_ks_skin_result(obj):
        """
        格式化旷视测肤数据
        :param obj:
        :return:
        """
        _data = {}
        if not obj:
            return _data

        _data = {
            'id': obj.id,
            'skin_color': obj.skin_color,
            'skin_age': obj.skin_age,
            'eye_bags': obj.eye_bags,
            'dark_circle': obj.dark_circle,
            'forehead_wrinkle': obj.forehead_wrinkle,
            'crows_feet': obj.crows_feet,
            'eye_finelines': obj.eye_finelines,
            'glabella_wrinkle': obj.glabella_wrinkle,
            'wrinkles': obj.wrinkles,
            'skin_oil': obj.skin_oil,
            'black_head': obj.black_head,
            'pores': obj.pores,
            'acne': obj.acne,
            'mole': obj.mole,
            'skin_spot': obj.skin_spot,

            'image_url': obj.image_url,
            'device_id': obj.device_id,
            'user_id': obj.user_id,
            'created_time': obj.created_time.strftime("%Y-%m-%d %H:%M:%S"),
        }

        return _data


class SkinBase(object):
    model = None
    base_query = Q(is_online=True)
    filter_query = Q()

    @classmethod
    def _get_info_by_query(cls, filter_query):
        result = {}

        if filter_query:
            filter_query &= cls.base_query
            obj = cls.model.objects.filter(filter_query).order_by("-id").first()
            if obj:
                result = to_dict(obj, excludes=["is_online", "created_time", "updated_time"])

            result["is_surgery"] = PolymerSurgery.objects.filter(polymer_id=result.get("polymer_id", 0),
                                                                 is_surgery=True).exists()

        return result

    @staticmethod
    def convert_filter_query(filters, filter_params_dic):

        filter_query = Q()
        filter_query.connector = "AND"

        if all([filters.get(k) in v for k, v in filter_params_dic.items()]):
            for param in filter_params_dic:
                filter_query.children.append((param, filters[param]))

        return filter_query


class SkinAgeService(SkinBase):
    """肤龄"""
    model = SkinAge

    @classmethod
    def get_skin_age_info(cls, filters):

        if not filters:
            return {}

        skin_age = filters.get("skin_age", 0)
        # 最大，最小 均是闭区间
        filter_query = Q(min_age__lte=skin_age, max_age__gte=skin_age)
        result = cls._get_info_by_query(filter_query)

        return result


class SkinOilService(SkinBase):
    """油脂"""
    model = SkinOil

    @classmethod
    def get_skin_oil_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "t_zone": SKIN_CONF_T_ZONE_TYPE,
            "chin": SKIN_CONF_CHIN_TYPE,
            "cheek": SKIN_CONF_CHEEK_TYPE,
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class HeiTouService(SkinBase):
    """黑头毛孔"""
    model = Heitou

    @classmethod
    def get_heitou_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "heitou_level": SKIN_CONF_HEITOU_TYPE,
            "maokong_level": SKIN_CONF_MAOKONG_TYPE,
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class AcneService(SkinBase):
    """痘痘"""
    model = Acne

    @classmethod
    def get_acne_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "level": SKIN_CONF_ACNE_TYPE,
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class SmoothLevelService(SkinBase):
    """光滑度"""
    model = Smoothlevel

    @classmethod
    def get_smooth_level_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "level": SKIN_CONF_SMOOTH_TYPE,
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result

    @classmethod
    def get_smooth_all_images_info(cls):
        """
        获取所有的图片
        :return:
        """
        _all_smooth_values = set(v for v, _ in SKIN_CONF_SMOOTH_TYPE)
        smooth_list = cls.model.objects.filter(
            is_online=True).order_by("-id").values("level", "level_image")

        result = []
        _smooth_remove_set = set()
        for item in smooth_list:
            _level = item["level"]
            _image_url = item["level_image"]

            if _level not in _smooth_remove_set:
                _smooth_remove_set.add(_level)
                result.append({
                    "smooth_level_id": _level,  # 皮肤光滑度等级
                    "image_url": _image_url,  # 对应图片
                })

            # 当值全部获取后，退出
            if not _smooth_remove_set.symmetric_difference(_all_smooth_values):
                break

        return result


class HeiYanQuanService(SkinBase):
    """黑眼圈"""
    model = HeiYanQuan

    @classmethod
    def get_dark_circle_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "pigmental": SKIN_CONF_PIGMENTAL_TYPE,    # 色素
            "vascular": SKIN_CONF_VASCULAR_TYPE,     # 血管
            "struct": SKIN_CONF_STRUCT_TYPE,    # 结构
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class SkinColorService(SkinBase):
    """肤色"""
    model = SkinColor

    @classmethod
    def get_skin_color_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_params_dic = {
            "color_level": list(range(1, 9)),   # 色号
            "color_temperature": SKIN_CONF_COLOR_TEMP_TYPE,  # 色温
        }

        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class ActWrinklesService(SkinBase):
    """
    法令纹
    """
    model = ActWrinkle

    @classmethod
    def get_wrinkles_info(cls, filters):
        result = {}
        if not filters:
            return result

        filter_params_dic = {
            "state": SKIN_CONF_ACT_WRINKLE_TYPE,  # 法令纹状态
        }
        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class EyeBagService(SkinBase):
    """
    眼袋
    """
    model = EyeBag

    @classmethod
    def get_eye_bag_info(cls, filters):
        result = {}
        if not filters:
            return result

        filter_params_dic = {
            "state": SKIN_CONF_EYE_BAG_TYPE,  # 眼袋状态
        }
        filter_query = cls.convert_filter_query(filters, filter_params_dic)
        result = cls._get_info_by_query(filter_query)

        return result


class SkinTypeService(SkinBase):
    """旷视测肤"""
    model = SkinType

    @classmethod
    def get_skintype_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_query = cls.face_filter_query(filters)
        result = cls._get_info_by_query(filter_query)

        return result

    @classmethod
    def face_filter_query(cls, filters):
        filter_query = Q()
        filter_query.connector = "AND"
        filter_query.children.append(('type_content', filters['skin_type']))
        filter_query.children.append(('type_value', filters['skin_value']))
        return filter_query

    @classmethod
    def get_skintype_all_images_info(cls):
        """
        获取所有的图片
        :return:
        """
        _all_skintype_values = set(v for v, _ in KS_SKIN_ALL_TYPE)
        skintype_list = cls.model.objects.filter(
            is_online=True).order_by("-id").values("type_value", "type_image")

        result = []
        _skintype_remove_set = set()
        for item in skintype_list:
            _type_value = item["type_value"]
            _image_url = item["type_image"]

            if _type_value not in _skintype_remove_set:
                _skintype_remove_set.add(_type_value)
                result.append({
                    "type_value_id": _type_value,  # 对应值
                    "image_url": _image_url,  # 图片
                })

            # 当值全部获取后，退出
            if not _skintype_remove_set.symmetric_difference(_all_skintype_values):
                break

        return result


class BlackheadPoreService(SkinBase):
    """旷视黑头毛孔"""
    model = BlackheadPore

    @classmethod
    def get_blackheadpore_info(cls, filters):
        result = {}

        if not filters:
            return result

        filter_query = cls.face_filter_query(filters)
        result = cls._get_info_by_query(filter_query)

        return result

    @classmethod
    def face_filter_query(cls, filters):
        filter_query = Q()
        filter_query.connector = "AND"
        filter_query.children.append(('blackhead_level', filters['blackhead']))
        filter_query.children.append(('pore_level', filters['pores']))
        return filter_query

