import logging


from django.core.paginator import Paginator

from domain.dataset import DataSet
from domain.imdb.media_domain import Media
from domain.imdb.episode_domain import Episode
from domain.imdb.value_object import CategoryValue
from injector.models import TaskModel
from injector.models import CdnMediaInformation
from injector.models import CdnEpisodeInformation
from injector.models import MediaStorageModel

from domain.injector.task_domain import Task

logger = logging.getLogger(__file__)


# cdn媒资改变信息
class CdnMedia(DataSet):
    model = CdnMediaInformation

    @classmethod
    def search(cls, media_id, partner_id):
        return cls.model.objects.filter(media_id=media_id, partner_id=partner_id).first()

    @classmethod
    def search_by_id(cls, cdn_id):
        return cls.model.objects.filter(id=cdn_id).first()

    @classmethod
    def add(cls, info):
        cdn_media = cls.model.objects.create(**info)
        return cdn_media

    @classmethod
    def edit(cls, cdn_id, info):
        cls.model.objects.filter(id=cdn_id).update(**info)
        return

    @classmethod
    def save(cls, media_id, params):
        cdn_id = int(params.pop("cid", 0))
        info = {
            "verpic": params.get("verpic", ""),
            "horpic": params.get("horpic", ""),
            "category": params.get("category", ""),
            "definition": int(params.get("definition", 2)),
            "is_charge": int(params.get("is_charge", 1)),
            "status": int(params.get("status", 1)),
            "media_id": media_id,
            "partner_id": int(params.get("partner_id", 0))
        }
        if cdn_id:
            cls.edit(cdn_id, info)
            cdn_media_id = cdn_id
        else:
            cdn_media = cls.add(info)
            cdn_media_id = cdn_media.id
        return cdn_media_id

    @classmethod
    def config(cls):
        category = CategoryValue.category_map()
        definition = {i[0]: i[1] for i in cls.model.DEFINITION_CHOICES}
        status = {1: "上线", 0: "下线"}
        is_charge = {1: "付费", 0: "免费"}
        return {
            "category": category,
            "status": status,
            "is_charge": is_charge,
            "definition": definition
        }

    @classmethod
    def detail(cls, cdn_media):
        return {
            "cid": cdn_media.id if cdn_media else 0,
            "verpic": cdn_media.verpic if cdn_media else "",
            "horpic": cdn_media.horpic if cdn_media else "",
            "status": cdn_media.status if cdn_media else "",
            "category": cdn_media.category if cdn_media else "",
            "definition": cdn_media.definition if cdn_media else "",
            "is_charge": cdn_media.is_charge if cdn_media else "",
            "partner_id": cdn_media.partner.id if cdn_media else "",
            "partner_name": cdn_media.partner.name if cdn_media else "",
            "partner_alias": cdn_media.partner.alias if cdn_media else "",
            "exist": True if cdn_media else False
        }


# Cdn工单
class CDNEpisode(DataSet):
    model = CdnEpisodeInformation

    @classmethod
    def add(cls, info):
        work_order = cls.model.objects.create(**info)
        return work_order

    @classmethod
    def edit(cls, cdn_id, info):
        cls.model.objects.filter(id=cdn_id).update(**info)
        return

    @classmethod
    def to_dict(cls, obj):
        cdn_media = obj.cdn_media
        episode = obj.episode
        media = Media(cdn_media.media_id).detail()
        cdn_media = CdnMedia.detail(cdn_media)
        episode = Episode().detail(episode.id)
        work_order = {
            "id": obj.id,
            "play_url": obj.play_url,
            "episode_verpic": obj.episode_verpic,
            "episode_horpic": obj.episode_horpic,
            "storage_type": obj.storage_type,
            "storage_definition": obj.storage_definition,
            "status": obj.status,
            "is_charge": obj.is_charge,
            "storage_id": obj.storage_id,
            "create_time": obj.create_time.strftime("%Y-%m-%d %H:%M:%S")
        }
        return {
            "media": media,
            "cdn_media": cdn_media,
            "episode": episode,
            "work_order": work_order
        }

    @classmethod
    def detail(cls, work_id):
        res = dict()
        work_order = cls.model.objects.filter(pk=work_id).first()
        if work_order:
            res = cls.to_dict(work_order)
        return res

    @classmethod
    def get_list(cls, media_name, partner, status, page=1, page_size=20):
        query = dict()
        if media_name:
            query["cdn_media__media__name__icontains"] = media_name
        if partner:
            query["cdn_media__partner__id"] = partner
        if not (status is None) and status != "":
            query["status"] = int(status)
        query = cls.model.objects.filter(**query).order_by("-id")
        pager = Paginator(query, page_size)
        objs = pager.get_page(page)
        return {
            "count": pager.count,
            "total_page": pager.num_pages,
            "media_list": [cls.to_dict(obj) for obj in objs]
        }

    @classmethod
    def config(cls):
        definition = {i[0]: i[1] for i in cls.model.STORAGE_DEFINITION}
        storage_type = {i[0]: i[1] for i in cls.model.STORAGE_TYPE}
        status = {1: "上线", 0: "下线"}
        is_charge = {1: "付费", 0: "免费"}
        return {
            "storage_type": storage_type,
            "status": status,
            "is_charge": is_charge,
            "definition": definition
        }

    @classmethod
    def save(cls, media_id, cdn_id, params):
        work_id = int(params.get("work_id", 0))
        play_url = params.get("play_url", "")
        storage_id = int(params.get("storage_id", 0))
        episode_id = int(params.get("episode_id", 0))
        cdn_media_id = int(params.get("cdn_media_id", 0))
        storage_definition = int(params.get("storage_definition", 2))
        episode = Episode().detail(episode_id)
        if not cdn_media_id:
            cdn_media_id = cdn_id
        if not storage_id:
            storage_info = {
                "media_id": media_id,
                "episode_id": episode_id,
                "name": "{}_{}".format(episode["media"]["name"], episode["serial_num"]),
                "content_type": storage_definition,
                "v_bit_rate": 0,
                "width": 16,
                "height": 9,
                "size": 0,
                "a_channels": 0,
                "a_bit_rate": 0,
                "a_sample_rate": 0,
                "bit_rate": 0,
                "url": play_url,
                "is_delete": True
            }
            storage = MediaStorageModel.objects.create(**storage_info)
            storage_id = storage.id
        info = {
            "play_url": play_url,
            "episode_verpic": params.get("episode_verpic", ""),
            "episode_horpic": params.get("episode_horpic", ""),
            "storage_type": int(params.get("storage_type", 1)),
            "storage_definition": storage_definition,
            "status": int(params.get("status", 1)),
            "is_charge": int(params.get("is_charge", 1)),
            "cdn_media_id": cdn_media_id,
            "storage_id": storage_id,
            "episode_id": episode_id
        }
        if work_id:
            cls.edit(work_id, info)
        else:
            cls.add(info)
        return storage_id, episode_id, episode["serial_num"]

    @classmethod
    def exists_work(cls, media_id, partner_id, episode_id):
        # 判断是否已经创建过该媒体及合作商下的这集分集工单
        cdn_media = CdnMedia.search(media_id, partner_id)
        is_created = False
        if cdn_media:
            is_created = CDNEpisode.model.objects.filter(cdn_media_id=cdn_media.id, episode_id=episode_id).exists()
        return is_created

    @classmethod
    def bulk_edit(cls, cdn_ids, info):
        cls.model.objects.filter(storage__in=cdn_ids).update(**info)
        return

    # 根据cdn工单获取task任务
    def for_work_order_get_task(self, storage_ids):
        orders = self.model.objects.filter(
            storage__in=storage_ids
        ).select_related("cdn_media").values("cdn_media__partner_id", "storage_id")
        tasks = list()
        for order in orders:
            tasks.append(
                TaskModel.objects.filter(
                    partner_id=order["cdn_media__partner_id"], storage_id=order["storage_id"]
                ).first()
            )
        return [Task.to_dict(task) for task in tasks]

