# coding: utf-8
from collections import defaultdict
from uuid import uuid4

from django.conf import settings
from django.db import transaction
from gm_types.face import GoldValueDefineType, GoldSkinValue

from api.models.face.cheek_style import PointLocation, GoldPercentDefine, GoldSkinInfo
from rpc.decorators import bind


@bind('hera/plastic/gold_percent_defines')
def gold_percent_define_list(page=1, page_size=10, filters={}, sort_fields=[]):
    """ 美学比例值列表 """
    result = {
        'data': [],
        'count': 0,
    }
    defines = GoldPercentDefine.objects.using(settings.SLAVE_DB_NAME).filter(**filters)
    result['count'] = defines.count()
    define_list = list(defines.order_by(*sort_fields)[(page-1)*page_size: page*page_size])
    define_ids = [item.id for item in define_list]

    point_configs = PointLocation.objects.using(settings.SLAVE_DB_NAME).filter(
        gold_percent_define_id__in=define_ids
    ).exclude(is_special=1).values_list('id', 'name', 'gold_percent_define_id')
    configs = defaultdict(list)
    for (_id, name, gold_percent_define_id) in point_configs:
        configs[gold_percent_define_id].append({
            'id': _id,
            'name': name,
        })

    for item in define_list:
        config = configs.get(item.id, [])
        config_data = {
            "id": item.id,
            'is_online': item.is_online,
            'name': item.name,
            'define_type': item.define_type,
            'point_location_one': config and config[0].get('name') or '',
            'point_location_two': '',
        }
        if len(config) >= 2:
            config_data.update({'point_location_two': config and config[1].get('name')})
        result['data'].append(config_data)

    return result


@bind('hera/plastic/gold_percent_define')
def gold_percent_define_by_id(define_id):
    """ 获取美学比例值 """
    result = {}
    if not define_id:
        return result

    try:
        define = GoldPercentDefine.objects.using(settings.SLAVE_DB_NAME).get(id=define_id)
    except GoldPercentDefine.DoesNotExist:
        return result
    skin_info = GoldSkinInfo.objects.using(settings.SLAVE_DB_NAME).filter(gold_percent_define_id=define.id).first()
    result = {
        'id': define.id,
        'name': define.name,
        'define_type': define.define_type,
        'is_online': define.is_online,
        'skin_type_max_diff_value': skin_info.skin_type_max_diff_value if skin_info else '',
        'skin_type_value_negative': skin_info.skin_type_value_negative if skin_info else '',
        'special_point_config': {},
        'point_config': [],
    }

    point_configs = PointLocation.objects.using(settings.SLAVE_DB_NAME).filter(
        gold_percent_define_id=define.id
    )

    for item in point_configs:
        data = {
                "id": item.id,
                "point_one": item.point_one,
                "point_one_type": item.point_one_type,
                'point_two': item.point_two,
                'point_three': item.point_three,
                "point_max_diff_value": item.point_max_diff_value,
                "point_diff_value_negative": item.point_diff_value_negative,
                'name': item.name
            }
        if item.is_special:
            result['special_point_config'] = data
            result['special_point_config'].update({
                "included_angle_type": item.included_angle_type,
            })
        else:
            data.update({
                "point_two_type": item.point_two_type,
                'point_three_type': item.point_three_type,
                "included_angle_type": item.included_angle_type,
                "is_denominator": item.is_denominator,
            })
            result['point_config'].append(data)

    return result


@transaction.atomic
@bind('hera/plastic/gold_percent_define/edit')
def gold_percent_define_edit(define_data, point_data, skin_data, define_id=None):
    """
    编辑、新增美学比例值
    :param define_data:     配置
    :param point_data:      点位
    :param skin_data:       肤质
    :param define_id:       配置id
    :return:
    """
    result = {
        'data': None,
        'message': 'fail',
        'error': 0,
    }

    if not any([define_id, define_data, point_data, skin_data]):
        return result

    if not define_id:
        if GoldPercentDefine.objects.filter(name=define_data.get('name')).exists():
            result['error'], result['message'] = 1, u'已经存在相同名称'
            return result

        define_data['key'] = uuid4()
        define = GoldPercentDefine.objects.create(**define_data)
        skin_type = 0
        for index, des in GoldSkinValue:
            if des == define.name:
                skin_type = index
                break

        # 肤质
        if skin_data:
            skin_data.update({
                'gold_percent_define_id': define.id,
                'skin_type': skin_type,
            })
            skin_info = GoldSkinInfo.objects.create(**skin_data)
        # 点位
        for item in point_data:
            item.pop('id', None)
            if not item.get('point_three'):
                item['point_three'] = 0
            item['gold_percent_define_id'] = define.id
            PointLocation.objects.create(**item)

    else:
        define = GoldPercentDefine.objects.get(id=define_id)
        if GoldPercentDefine.objects.filter(name=define_data.get('name')).exclude(id=define.id).exists():
            result['error'], result['message'] = 1, u'已经存在相同名称'
            return result
        for k, v in define_data.items():
            setattr(define, k, v)
        define.save()

        # 肤质数据
        if int(define.define_type) == GoldValueDefineType.SKIN:
            # 肤质类型要把点位数据删掉
            PointLocation.objects.filter(gold_percent_define_id=define.id).delete()
            skin_info = GoldSkinInfo.objects.using(settings.SLAVE_DB_NAME).filter(
                gold_percent_define_id=define.id
            ).first()
            skin_type = 0
            for index, des in GoldSkinValue:
                if des == define.name:
                    skin_type = index
                    break
            skin_data.update({
                'skin_type': skin_type,
                'gold_percent_define_id': define.id,
            })
            if not skin_info:
                GoldSkinInfo.objects.create(**skin_data)
            else:
                for k, v in skin_data.items():
                    setattr(skin_info, k, v)
                skin_info.save()

        # 点位数据
        if point_data:
            PointLocation.objects.filter(gold_percent_define_id=define.id).delete()
            for item in point_data:
                point_id = item.pop('id', None)
                if not item.get('point_three'):
                    item['point_three'] = 0

                item['gold_percent_define_id'] = define.id
                PointLocation.objects.create(**item)
    result.update({
        'data': define.id,
        'message': 'success',
    })

    return result
