# -*- coding: UTF-8 -*-

import json
from django.db.models import Q

from gm_dataquery.dict_mixin import to_dict
from gm_dataquery.dataquery import DataSQLQuery, DataBuilder
from gm_dataquery.db import DB

from gm_types.error import ERROR
from gm_types.wiki import PRODUCT_PARAMS, PRODUCT_TYPE, PRODUCT_IMAGE_TYPE
from gm_types.gaia import VIDEO_LIBRARY_VIDEO_TYPE

from rpc.exceptions import GaiaRPCFaultException
from wiki.models.product import (
    Product,
    ProductAttestation,
    ProductImage,
    ProductParams,
    ProductRelationKeyWords,
)
from wiki.models.video import VideoLibrary, VideoRelationWord
from wiki.logices.product import get_product_params_type_by_type
from wiki.logices.common_query import (
    NewWikiRelationWords,
    wiki_data_create,
    wiki_data_update,
    wiki_video_create,
    wiki_video_update,
)

VIDEOURL = 'http://video-static.igengmei.com/'


class ProductDB(DataBuilder, NewWikiRelationWords):

    def getval_image_url(self, obj):
        return list(obj.images.filter(image_type=PRODUCT_IMAGE_TYPE.PRODUCT).
                    values_list('image_url', flat=True))

    def getval_drug_type(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.TYPE) 

    def getval_concentration(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.CONCENTRATION) 

    def getval_molecular(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.MOLECULAR) 

    def getval_part(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.PART) 

    def getval_property(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.PROPERTY) 

    def getval_dispersity(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.DISPERSITY) 

    def getval_size(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.SIZE) 

    def getval_wave_length(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.WAVE_LENGTH) 

    def getval_energy(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.ENERGY) 

    def getval_pulse_width(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.PULSE_WIDTH) 

    def getval_max_energy(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.MAX_ENERGY) 

    def getval_spot_size(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.SPOT_SIZE) 

    def getval_photo_sys(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.PHOTO_SYS) 

    def getval_focus_depth(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.FOCUS_DEPTH) 

    def getval_purity(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.PURITY) 

    def getval_anti_aging(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.ANTI_AGING) 

    def getval_ductility(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.DUCTILITY) 

    def getval_resist_pressure(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.RESIST_PRESSURE) 

    def getval_abrasion(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.ABRASION) 

    def getval_surface(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.SURFACE) 

    def getval_shape(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.SHAPE) 

    def getval_transparence(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.TRANSPARENCE) 

    def getval_flexibility(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.FLEXIBILITY) 

    def getval_cohesion(self, obj):
        return get_product_params_type_by_type(obj.id, PRODUCT_PARAMS.COHESION)

    def getval_video_data(self, obj):
        video_libs = VideoLibrary.objects.filter(source_id=obj.id, is_online=True,
                                                 video_type__in=[VIDEO_LIBRARY_VIDEO_TYPE.MATERIALS,
                                                                 VIDEO_LIBRARY_VIDEO_TYPE.DRUG,
                                                                 VIDEO_LIBRARY_VIDEO_TYPE.INSTRUMENT])
        index, result = 0, {}
        item_list = list(ProductRelationKeyWords.objects.filter(product_id=obj.id, is_effect=True).values_list('wordrel_id',
                                                                                                            flat=True))
        for video_lib in video_libs:
            word_list = list(VideoRelationWord.objects.filter(video_id=video_lib.id).values_list('word_id', flat=True))
            word_list.extend(item_list)
            result[index] = {
                "img": video_lib.raw_image_url,
                "video": video_lib.raw_video_url,
                "tags": word_list,
                "order": video_lib.ordering,
                "key": video_lib.raw_video_url,
            }
            index += 1
        return result

@DB
class ProductDQ(DataSQLQuery):
    model = Product
    data_model = ProductDB

    drug_params = {
        PRODUCT_PARAMS.TYPE: 'drug_type',
        PRODUCT_PARAMS.CONCENTRATION: 'concentration',
        PRODUCT_PARAMS.MOLECULAR: 'molecular',
        PRODUCT_PARAMS.PART: 'part',
        PRODUCT_PARAMS.PROPERTY: 'property',
        PRODUCT_PARAMS.DISPERSITY: 'dispersity',
        PRODUCT_PARAMS.SIZE: 'size',
    }
    instrument_params = {
        PRODUCT_PARAMS.WAVE_LENGTH: 'wave_length',
        PRODUCT_PARAMS.ENERGY: 'energy',
        PRODUCT_PARAMS.PULSE_WIDTH: 'pulse_width',
        PRODUCT_PARAMS.MAX_ENERGY: 'max_energy',
        PRODUCT_PARAMS.SPOT_SIZE: 'spot_size',
        PRODUCT_PARAMS.PHOTO_SYS: 'photo_sys',
        PRODUCT_PARAMS.FOCUS_DEPTH: 'focus_depth',
    }
    materials_params = {
        PRODUCT_PARAMS.PURITY: 'purity',
        PRODUCT_PARAMS.ANTI_AGING: 'anti_aging',
        PRODUCT_PARAMS.DUCTILITY: 'ductility',
        PRODUCT_PARAMS.RESIST_PRESSURE: 'resist_pressure',
        PRODUCT_PARAMS.COHESION: 'cohesion',
        PRODUCT_PARAMS.ABRASION: 'abrasion',
        PRODUCT_PARAMS.SURFACE: 'surface',
        PRODUCT_PARAMS.SHAPE: 'shape',
        PRODUCT_PARAMS.TRANSPARENCE: 'transparence',
        PRODUCT_PARAMS.FLEXIBILITY: 'flexibility',
    }

    def update(self, updates, **kwargs):
        objs = self.model.objects.filter(**kwargs)

        if updates.get("video_data"):
            if objs and objs[0]:
                if objs[0].product_type == PRODUCT_TYPE.DRUG:
                    video_type = VIDEO_LIBRARY_VIDEO_TYPE.DRUG
                if objs[0].product_type == PRODUCT_TYPE.INSTRUMENT:
                    video_type = VIDEO_LIBRARY_VIDEO_TYPE.INSTRUMENT
                if objs[0].product_type == PRODUCT_TYPE.MATERIALS:
                    video_type = VIDEO_LIBRARY_VIDEO_TYPE.MATERIALS
            video_data = str(updates.get("video_data"))
            video_data = json.loads(video_data)
            wiki_video_update(video_data=video_data, wiki_id=int(kwargs.get('id')), video_type=video_type)

        for obj in objs:
            params = {}
            if obj.product_type == PRODUCT_TYPE.DRUG:
                params = self.drug_params
            if obj.product_type == PRODUCT_TYPE.INSTRUMENT:
                params = self.instrument_params
            if obj.product_type == PRODUCT_TYPE.MATERIALS:
                params = self.materials_params
            for k, v in params.items():
                if updates.get(v) is not None:
                    params, _ = ProductParams.objects.get_or_create(product=obj, params_type=k)
                    params.params_message = updates[v]
                    params.save()

            if updates.get('similar_product') and str(obj.id) in updates.get('similar_product'):
                raise GaiaRPCFaultException(ERROR.UNIVERSAL, u'相似物品不能与自己关联', data=None)
            if updates.get('image_url'):
                image_url = updates.pop('image_url')
                ProductImage.objects.filter(product=obj, image_type=PRODUCT_IMAGE_TYPE.PRODUCT).delete()
                ProductImage.objects.bulk_create([ProductImage(
                    product=obj, image_type=PRODUCT_IMAGE_TYPE.PRODUCT, image_url=url
                ) for url in image_url if url])

            wiki_data_update(obj.id, updates, ProductRelationKeyWords, "product_id")

        return super(ProductDQ.sqlquery, self).update(updates, **kwargs)

    def create(self, **kwargs):
        image_url = kwargs.pop('image_url')
        similar_product = kwargs.pop('similar_product')
        kwargs.pop('attestation_info')
        kwargs.pop('verify_image')
        params = {}
        create_params = {}
        video_type = 0
        video_data = kwargs.pop('video_data', None)

        if kwargs['product_type'] == PRODUCT_TYPE.DRUG:
            params = self.drug_params
            video_type = VIDEO_LIBRARY_VIDEO_TYPE.DRUG
        if kwargs['product_type'] == PRODUCT_TYPE.INSTRUMENT:
            params = self.instrument_params
            video_type = VIDEO_LIBRARY_VIDEO_TYPE.INSTRUMENT
        if kwargs['product_type'] == PRODUCT_TYPE.MATERIALS:
            params = self.materials_params
            video_type = VIDEO_LIBRARY_VIDEO_TYPE.MATERIALS

        for k, v in params.items():
            create_params[k] = kwargs.pop(v)

        obj = wiki_data_create(self.model, ProductRelationKeyWords, "product_id", **kwargs)
        # obj = self.model.objects.create(**kwargs)
        obj.similar_product = similar_product
        [ProductImage.objects.create(product=obj, image_type=PRODUCT_IMAGE_TYPE.PRODUCT,
                                     image_url=url) for url in image_url if url]
        [ProductParams.objects.create(product=obj, params_type=k,
                                      params_message=v) for k, v in create_params.items()]

        # 处理视频
        if video_data:
            video_data = json.loads(str(video_data))
            wiki_video_create(wiki_id=obj.id, video_data=video_data, video_type=video_type)
        return to_dict(obj)


@DB
class ProductAttestationDQ(DataSQLQuery):
    model = ProductAttestation

    def update(self, updates, **kwargs):
        if updates.get('attestation_type'):
            q = Q(product_id__in=[
                pro_att.product_id for pro_att in self.model.objects.filter(**kwargs)
            ]) & Q(attestation_type=updates['attestation_type'])
            if self.model.objects.exclude(**kwargs).filter(q).exists():
                raise GaiaRPCFaultException(ERROR.UNIVERSAL, u'该物品已有相关认证', data=None)
        return super(ProductAttestationDQ.sqlquery, self).update(updates, **kwargs)

    def create(self, **kwargs):
        q = Q(product_id=kwargs['product_id'],
              attestation_type=kwargs['attestation_type'])
        if self.model.objects.filter(q).exists():
            raise GaiaRPCFaultException(ERROR.UNIVERSAL, u'该物品已有相关认证', data=None)
        return super(ProductAttestationDQ.sqlquery, self).create(**kwargs)

@DB
class ProductImageDQ(DataSQLQuery):
    model = ProductImage
