# coding=utf-8

from __future__ import unicode_literals, absolute_import, print_function

import datetime
from collections import defaultdict

from gm_upload import IMG_TYPE, ImgUrlField

from django.db import models
from django.db.models import Q

from gm_types.gaia import (
    SLIDE_USER_TYPE, SLIDE_PAYMENT_TYPE,
    CATEGORY_TEMPLATE_TYPE, POLYMER_CONTENT_TYPE, SLIDE_POSITION,
    SOURCE_POSITION_DEVICE_TYPE, PLATFORM_CHOICES, WORLD_AREA_TYPE)
from api.models import (
    Slide, Gadget, Tag, City,
    Province)
from api.models import (
    Slide, Gadget, Tag,
    ZhiboConfig, TagV3)
from polymer.models import Polymer
from wiki.models import Brand

# 品类聚合页model

class BaseModel(models.Model):

    class Meta:
        abstract = True

    is_online = models.BooleanField(verbose_name=u"是否有效", default=True)
    create_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True, db_index=True)
    is_deleted = models.BooleanField(verbose_name='是否删除', default=False)


class CategoryGroup(BaseModel):
    class Meta:
        verbose_name = u'小组'
        db_table = 'category_group'
        app_label = 'category'

    polymer = models.ForeignKey(Polymer, null=True, verbose_name=u'关联内容聚合')
    s_title = models.CharField(u'小标题', max_length=128, null=False, default='')
    b_title = models.CharField(u'大标题', max_length=128, null=False, default='')
    img = ImgUrlField(u'背景图', max_length=255, null=False, default='', img_type=IMG_TYPE.CATEGORY_POLYMER)
    start_time = models.DateTimeField(u'开始时间', null=True)
    end_time = models.DateTimeField(u'结束时间', null=True)


class CategoryPolymer(BaseModel):
    class Meta:
        verbose_name = u'品类聚合页'
        db_table = 'category_polymer'
        app_label = 'category'

    name = models.CharField(u'名称', max_length=128, default='')
    search_word = models.CharField(u'搜索词', max_length=128, null=False, default='')
    user_type = models.CharField(u'用户类型', max_length=2, choices=SLIDE_USER_TYPE.choices, default=SLIDE_USER_TYPE.ALL_USER, null=False)
    payment_type = models.CharField(u'有无支付', max_length=2, choices=SLIDE_PAYMENT_TYPE.choices, default=SLIDE_PAYMENT_TYPE.ALL_PAYMENT, null=False)
    start_time = models.DateTimeField(u'开始时间')
    end_time = models.DateTimeField(u'结束时间')
    operation_level_one_id = models.IntegerField(verbose_name='运营一级分类id',null=True, blank=True)

    @classmethod
    def get_category_polymer_by_id(cls, cp_id):
        if not cp_id:
            return None

        try:
            return cls.objects.get(id=cp_id)
        except:
            return None

    @classmethod
    def get_recommend(cls, cp_id=None, city_id=None):
        '''
        获取品类对应的推荐内容
        '''
        result = {}
        if not cp_id:
            return result

        cp_obj = cls.get_category_polymer_by_id(cp_id)
        if not cp_obj:
            return None

        time_now = datetime.datetime.now()
        common_query = Q(is_online=True, start_time__lte=time_now, end_time__gte=time_now)
        city_query = Q(is_related_city=False)
        if city_id:
            temp_query = Q(category_recommend_cities__city_id=city_id, is_related_city=True)
            city_query = city_query | temp_query
        #推荐数据
        recommend_data = cp_obj.categorypolymer_recommends.filter(common_query, city_query)
        recommend_data_list = list(recommend_data.values('id', 'rank', 'content_type', 'content_id'))
        type_id_data = defaultdict(list)
        for rd in recommend_data_list:
            type_id_data[rd['content_type']].append(rd)
        for k,v in type_id_data.items():
            v.sort(key=lambda x:x['rank'])
        result = dict(type_id_data)
        return result

    @classmethod
    def get_tags(cls, cp_id):
        result = []
        if not cp_id:
            return result

        cp_obj = cls.get_category_polymer_by_id(cp_id)
        if not cp_obj:
            return None

        res = list(cp_obj.tags.filter(tag__is_online=True).values('tag_id', 'tag__name', 'tag__tag_type'))
        for r in res:
            r['name'] = r.pop('tag__name') or ''
            r['tag_type'] = r.pop('tag__tag_type') or None
        return res

    @classmethod
    def get_tags_v3(cls, cp_id):
        result = []
        if not cp_id:
            return result

        cp_obj = cls.get_category_polymer_by_id(cp_id)
        if not cp_obj:
            return None

        category_polymer_tags_v3 = CategoryPolymerTagV3.objects.filter(category_id=cp_id)
        tags_v3 = TagV3.objects.filter(
            id__in=[cpt.tag_v3_id for cpt in category_polymer_tags_v3]
        )
        res = []
        for tag in tags_v3:
            tag_info = dict()
            tag_info["tag_id"] = tag.id
            tag_info["name"] = tag.name
            tag_info["tag_type"] = tag.tag_type
            res.append(tag_info)
        return res

    def get_groups(self):
        now_time = datetime.datetime.now()
        online_query = Q(group__start_time__lte=now_time, group__is_online=True)
        end_time_query = Q(group__end_time__isnull=True) | Q(group__end_time__gte=now_time)
        grp_objs = self.groups.all().filter(online_query, end_time_query)
        result = []
        for grp_obj in grp_objs:
            result.append(grp_obj.get_group_data())
        return result

    def get_areas(self):
        ply_area_objs = self.areas.all().filter(area__is_online=True)
        result = []
        for ply_obj in ply_area_objs:
            result.append(ply_obj.get_box_data())
        return result

    def get_gadgets(self):
        '''运营位'''
        now_time = datetime.datetime.now()
        online_query = Q(gadget__start_time__lte=now_time, gadget__is_online=True)
        end_time_query = Q(gadget__end_time__isnull=True) | Q(gadget__end_time__gte=now_time)
        gad_objs = self.gadgets.all().filter(online_query, end_time_query)
        result = []
        for gad_obj in gad_objs:
            result.append(gad_obj.gadget.get_data())
        return result

    def get_brands(self):
        '''品牌配置位'''
        ply_brand_objs = self.brands.all().filter(brand__is_online=True)
        result = []
        for ply_bra_obj in ply_brand_objs:
            result.append(ply_bra_obj.get_brand_data())
        return result

    def get_banners(self, city_id=None, device_type=SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE,
                    payment_type=SLIDE_PAYMENT_TYPE.ALL_PAYMENT, user_type=SLIDE_USER_TYPE.ALL_USER):
        '''轮播图'''
        now_time = datetime.datetime.now()
        online_query = Q(banner__effect_time__lte=now_time, banner__is_online=True)
        end_time_query = Q(banner__end_time__isnull=True) | Q(banner__end_time__gte=now_time)
        """新增加按照设备、用户类型、有无支付判断，修改原有城市逻辑判断"""
        region, country_id = (None, None)
        try:
            city = City.objects.get(id=city_id)
            if city.province_id:
                province = Province.objects.select_related('region').get(id=city.province_id)
                region = province.region
                country_id = province.country_id
        except City.DoesNotExist:
            pass
        # 规则如下：
        # 1. 定位在全部地区、无定位、定位在海外，只能看到全部地区的banner(不能看到配置具体城市的banner)
        # 2. 定位在具体城市，可以看到该城市、大区、全部地区的banner
        if not city_id or city_id in WORLD_AREA_TYPE or (region and region.english_name == 'haiwai') or \
                (country_id and country_id != 'china'):
            city_query = Q(banner__related_slide__isnull=True, banner__showregion__region__isnull=True)
        else:
            city_query = Q(banner__related_slide__city=city_id) | Q(banner__related_slide__isnull=True, banner__showregion__region__isnull=True)
            if region:
                city_query |= Q(banner__showregion__region=region)
        user_query = Q(banner__user_type__in=[user_type, SLIDE_USER_TYPE.ALL_USER])
        platform_query = Q(banner__device_type__in=[device_type, SOURCE_POSITION_DEVICE_TYPE.ALL_DEVICE_TYPE])
        payment_type_query = Q(banner__payment_type__in=[payment_type, SLIDE_PAYMENT_TYPE.ALL_PAYMENT])
        ply_ban_objs = self.banners.all().filter(online_query, end_time_query, city_query, user_query, platform_query, payment_type_query)
        result = []
        for pbo in ply_ban_objs:
            result.append(pbo.banner.slide_data())
        result.sort(key=lambda x:x.get('ordering'))
        return result


class CategoryArea(BaseModel):
    class Meta:
        verbose_name = u'品类区'
        db_table = 'category_area'
        app_label = 'category'

    style = models.SmallIntegerField(u'样式类型', choices=CATEGORY_TEMPLATE_TYPE)


class CategoryElement(BaseModel):
    class Meta:
        verbose_name = u'品类区元素'
        db_table = 'category_element'
        app_label = 'category'

    name = models.CharField(u'名称', max_length=128, null=False, default='')
    icon = ImgUrlField(u'icon图', max_length=255, null=False, default='', img_type=IMG_TYPE.CATEGORY_POLYMER)
    background_img = ImgUrlField(u'背景图', max_length=255, null=False, default='', img_type=IMG_TYPE.CATEGORY_POLYMER)
    pre_background_img = ImgUrlField(u'背景前图', max_length=255, null=False, default='', img_type=IMG_TYPE.CATEGORY_POLYMER)
    is_main_category = models.BooleanField(u'是否为主品类', default=False)
    category_type = models.SmallIntegerField(u'品类类型', choices=CATEGORY_TEMPLATE_TYPE)


class CategoryPolymerGroup(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联小组'
        db_table = 'category_polymer_group'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='groups')
    group = models.ForeignKey(CategoryGroup, verbose_name=u'小组', related_name='categories')

    # for backend
    def get_group_data(self):
        return {
            's_title': self.group.s_title,
            'b_title': self.group.b_title,
            'group_id': self.group.id,
            'group_image': self.group.img,
            'polymer_id': self.group.polymer.id
        }


class CategoryPolymerBanner(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联banner'
        db_table = 'category_polymer_banner'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='banners')
    banner = models.ForeignKey(Slide, verbose_name=u'banner', related_name='categories')


class CategoryPolymerArea(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联品类区'
        db_table = 'category_polymer_area'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='areas')
    area = models.ForeignKey(CategoryArea, verbose_name=u'品类区', related_name='categories')

    # for backend
    def get_all_elements(self):
        data = [element.get_element_data() for element in self.area.elements.all()]
        return sorted(data, key=lambda e:e.__getitem__('is_main_category'), reverse=True)

    def get_box_data(self):
        return {
            'id': self.area.id,
            'style': self.area.style,
            'boxes': self.get_all_elements()
        }


class CategoryAreaElement(BaseModel):
    class Meta:
        verbose_name = u'品类区关联元素'
        db_table = 'category_area_element'
        app_label = 'category'

    area = models.ForeignKey(CategoryArea, verbose_name=u'品类区', related_name='elements')
    element = models.ForeignKey(CategoryElement, verbose_name=u'品类区元素', related_name='areas')

    # for backend
    def get_element_data(self):
        return {
            'element_id': self.element.id,
            'tag_ids': list(self.element.tags.values_list('tag_id', flat=True)),
            'icon': self.element.icon,
            'background_img': self.element.background_img,
            'pre_background_img': self.element.pre_background_img,
            'is_main_category': 1 if self.element.is_main_category else 0,
            'box_name': self.element.name,
        }


class CategoryElementTag(BaseModel):
    class Meta:
        verbose_name = u'品类区元素关联标签'
        db_table = 'category_element_tag'
        app_label = 'category'

    element = models.ForeignKey(CategoryElement, verbose_name=u'品类区元素', related_name='tags')
    tag = models.ForeignKey(Tag, verbose_name=u'标签')


class CategoryElementTagV3(BaseModel):
    class Meta:
        verbose_name = u'品类区元素关联标签'
        db_table = 'category_element_tag_v3'
        app_label = 'category'

    element_id = models.IntegerField(verbose_name=u'品类区元素', db_index=True)
    tag_v3_id = models.IntegerField(verbose_name=u'标签V3', db_index=True)


class CategoryPolymerBrand(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联品牌'
        db_table = 'category_polymer_brand'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='brands')
    brand = models.ForeignKey(Brand, verbose_name=u'品牌', related_name='categories')

    # for backend
    def get_brand_data(self):
        return {
            'brand_id': self.brand.id,
            'brand_name': self.brand.name,
            'brand_image': self.brand.image_url
        }


class CategoryGadget(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联运营位'
        db_table = 'category_polymer_gadget'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='gadgets')
    gadget = models.ForeignKey(Gadget, null=True, verbose_name=u'运营位')


class CategoryPolymerTag(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联标签'
        db_table = 'category_polymer_tag'
        app_label = 'category'

    category = models.ForeignKey(CategoryPolymer, verbose_name=u'品类聚合', related_name='tags')
    tag = models.ForeignKey(Tag, null=True, verbose_name=u'标签')


class CategoryPolymerTagV3(BaseModel):
    class Meta:
        verbose_name = u'聚合页关联新标签v3'
        db_table = 'category_polymer_tag_v3'
        app_label = 'category'

    category_id = models.IntegerField(verbose_name=u"品类聚合页", db_index=True)
    tag_v3_id = models.IntegerField(verbose_name=u"标签", db_index=True)


class CategoryPolymerRecommend(BaseModel):
    class Meta:
        verbose_name = '品类运营推荐内容'
        db_table = 'category_polymer_recommend'
        app_label = 'category'

    categorypolymer = models.ForeignKey(CategoryPolymer, related_name="categorypolymer_recommends")
    rank = models.IntegerField('排序', default=100)
    content_type = models.CharField('推荐类型', max_length=30, choices=POLYMER_CONTENT_TYPE)
    content_id = models.CharField('内容ID', max_length=64)
    start_time = models.DateTimeField(verbose_name=u'开始时间', null=True)
    end_time = models.DateTimeField(verbose_name=u'结束时间', null=True)
    is_related_city = models.BooleanField(verbose_name=u'是否关联城市', default=False)

    def add_related_cities(self, cities, is_related_city=3):
        if not isinstance(cities, list) or is_related_city==1:
            return
        elif is_related_city==2:
            CategoryPolymerRecommendRelatedCities.objects.filter(categorypolymerrecommend=self).delete()
        elif is_related_city==3:
            old_cities = list(CategoryPolymerRecommendRelatedCities.objects.filter(
                categorypolymerrecommend=self
            ).values_list('city_id', flat=True))
            CategoryPolymerRecommendRelatedCities.objects.filter(
                city_id__in=set(old_cities) - set(cities),
                categorypolymerrecommend=self
            ).delete()
            CategoryPolymerRecommendRelatedCities.objects.bulk_create([
                CategoryPolymerRecommendRelatedCities(categorypolymerrecommend=self, city_id=city_id)
                for city_id in set(cities) - set(old_cities)
            ])

    def get_related_cities(self):
        return ','.join(list(self.category_recommend_cities.values_list('city__name', flat=True)))


class CategoryPolymerRecommendRelatedCities(BaseModel):
    class Meta:
        verbose_name = '品类运营推荐城市关联'
        db_table = 'category_polymer_recommend_cities'
        app_label = 'category'

    categorypolymerrecommend = models.ForeignKey(CategoryPolymerRecommend, verbose_name=u'关联推荐内容', related_name='category_recommend_cities')
    city = models.ForeignKey(City, verbose_name=u'关联城市')


class Category(BaseModel):
    '''
    用于定义标签的聚合
    '''
    class Meta:
        verbose_name = '品类定义'
        db_table = 'category_basic_category'
        app_label = 'category'

    name = models.CharField(verbose_name='品类名称', max_length=255, null=False)
    img_url = models.CharField(verbose_name='图片url', max_length=255, null=False)
    tag_ids = models.CharField(verbose_name='标签id, 英文逗号分隔', max_length=255, null=False)
    seq = models.IntegerField(verbose_name='序号', default=0)

    @classmethod
    def validate_category_id(cls, category_id_list):
        '''
        根据id获取对应品类的有效性
        '''
        try:
            return cls.objects.filter(id__in=category_id_list, is_online=True).count() == len(category_id_list)
        except:
            return False

    @classmethod
    def all_valid_category(cls):
        '''
        返回有效品类定义
        '''
        return list(cls.objects.filter(is_online=True).values('id', 'name', 'img_url').order_by('seq').all())


class CategoryMap(models.Model):
    '''
    用于医生后台和hera后台品类映射
    '''
    class Meta:
        verbose_name = '品类映射'
        db_table = 'category_map'
        app_label = 'category'

    sideskidcategory_id = models.IntegerField(verbose_name='首页横滑分类id', null=False)
    categorypolymer_id = models.IntegerField(verbose_name='品类聚合页id', null=False)
