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

import os
import time
import ffmpy
import hashlib
import json
import requests
from urlparse import urljoin

from celery import shared_task
from django.conf import settings

from gm_types.gaia import (
    VIDEO_CODE_STATUS,
    QINIU_VIDEO_HANDLE_STATUS_CODE,
)

from gm_upload import (
    set_video_watermark,
    set_image_water_mark_for_picture_and_save_to_qiniu,
    video_clipping,
    upload_file,
    video_delete,
)
from gm_upload.utils.qiniu_tool import QiniuTool

from wiki.models.video import VideoLibrary
from rpc.tool.log_tool import logging_exception


@shared_task
def update_video_library_cover_url(video_id):
    video_obj = VideoLibrary.objects.get(id=video_id)
    raw_image_url = video_obj.raw_image_url
    water_image_url = set_image_water_mark_for_picture_and_save_to_qiniu(
        raw_image_url,
        settings.WATER_MARK_URL_FOR_IMAGE,
        gravity="NorthEast",
    )
    video_obj.water_image_url = water_image_url
    video_obj.save(update_fields=["water_image_url"])


@shared_task
def set_video_library_water_mark_url(video_id):
    video_obj = VideoLibrary.objects.get(id=video_id)

    raw_video_url = video_obj.raw_video_url
    params = {
        "filename": raw_video_url,
        "newfilename": hashlib.md5(raw_video_url).hexdigest() + '.mp4',
        "water_mark_url": settings.WATER_MARK_URL_FOR_VIDEO,
    }
    pid = set_video_watermark(**params)

    video_obj.persistent_id = pid
    video_obj.persistent_status = VIDEO_CODE_STATUS.WAITING
    video_obj.save(update_fields=['persistent_id', 'persistent_status'])


@shared_task
def check_water_mark_video_library_data_is_finish():
    videos = VideoLibrary.objects.filter(persistent_status=VIDEO_CODE_STATUS.WAITING)
    for video in videos:
        try:
            video_persistent_id = video.persistent_id
            if video_persistent_id:
                result = json.loads(requests.get('http://api.qiniu.com/status/get/prefop?id=' +
                                                 video_persistent_id).text)
                # 状态码0成功，1等待处理，2正在处理，3处理失败，4通知提交失败。
                code = result['code']
                if code not in (QINIU_VIDEO_HANDLE_STATUS_CODE.SUCCESS, QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL):
                    continue
                elif code == QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL:
                    video.persistent_status = VIDEO_CODE_STATUS.FAIL
                    video.save(update_fields=['persistent_status'])
                else:
                    if result['items'][0]['code'] == QINIU_VIDEO_HANDLE_STATUS_CODE.SUCCESS:
                        water_video_url = result['items'][0]['key']
                        # 刷新cdn缓存
                        QiniuTool.refresh_qiniu_resource_cache([urljoin(settings.VIDEO_HOST, water_video_url)])

                        video.water_video_url = water_video_url
                        video.persistent_status = VIDEO_CODE_STATUS.SUCCESS
                        video.save(update_fields=['persistent_status', 'water_video_url'])
                    else:
                        video.persistent_status = result['items'][0]['code']
                        video.save(update_fields=['persistent_status'])
        except:
            logging_exception()


@shared_task
def wiki_video_library_fsm_runner():
    """
    状态机
    考虑封装成类，根据状态给对应worker添加任务
    :return:
    """

    # 截取视频前两秒
    clipping_id_list = list(VideoLibrary.objects.filter(
        persistent_clip_status=VIDEO_CODE_STATUS.NOSTART
    ).values_list("id", flat=True))
    for video_id in clipping_id_list:
        set_video_library_clipping_to_video.delay(video_id)

    # 检查七牛云截取状态
    check_id_list = list(VideoLibrary.objects.filter(
        persistent_clip_status=VIDEO_CODE_STATUS.WAITING
    ).values_list("id", flat=True))
    for video_id in check_id_list:
        check_video_library_clipping_is_finish.delay(video_id)

    # 将七牛云截取成功的 mp4 转换为 webP 动图并上传
    set_id_list = list(VideoLibrary.objects.filter(
        persistent_clip_status=VIDEO_CODE_STATUS.OPERATING_LOCAL
    ).values_list("id", flat=True))
    for video_id in set_id_list:
        set_video_webp_pic.delay(video_id)


@shared_task
def set_video_library_clipping_to_video(video_id):
    video = VideoLibrary.objects.get(id=video_id)
    video.persistent_clip_status = VIDEO_CODE_STATUS.WAITING
    url = video.raw_video_url
    hash_key = hashlib.md5(str(time.time())).hexdigest()
    pid = video_clipping(
        url,
        new_filename='{}_clip.mp4'.format(hash_key),
        video_type='mp4',
        water_mark_url=None
        # water_mark_url=settings.WATER_MARK_URL_FOR_VIDEO
    )
    video.persistent_clip_id = pid
    video.save(update_fields=['persistent_clip_id', 'persistent_clip_status'])


@shared_task
def check_video_library_clipping_is_finish(video_id):
    try:
        video = VideoLibrary.objects.get(id=video_id)
        if video.persistent_clip_status != VIDEO_CODE_STATUS.WAITING:
            return

        if video.persistent_clip_id:
            result = json.loads(requests.get('http://api.qiniu.com/status/get/prefop?id=' +
                                             video.persistent_clip_id).text)
            # 状态码0成功，1等待处理，2正在处理，3处理失败，4通知提交失败。
            code = result['code']
            if code not in (QINIU_VIDEO_HANDLE_STATUS_CODE.SUCCESS, QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL):
                return
            elif code == QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL:
                video.persistent_clip_status = VIDEO_CODE_STATUS.FAIL
                video.save(update_fields=['persistent_clip_status'])
            else:
                if result['items'][0]['code'] == QINIU_VIDEO_HANDLE_STATUS_CODE.SUCCESS:
                    mp4_key = result['items'][0]['key']

                    # 刷新cdn缓存
                    QiniuTool.refresh_qiniu_resource_cache([urljoin(settings.VIDEO_HOST, mp4_key)])

                    video.intercept_video_url = mp4_key
                    video.persistent_clip_status = VIDEO_CODE_STATUS.OPERATING_LOCAL
                    video.save(update_fields=['persistent_clip_status', 'intercept_video_url'])
                    # set_video_webp_pic.delay(video.id)
                else:
                    video.persistent_status = result['items'][0]['code']
                    video.save(update_fields=['persistent_clip_status'])

    except:
        logging_exception()


@shared_task
def set_video_webp_pic(video_id):
    video = VideoLibrary.objects.get(id=video_id)
    if video.persistent_clip_status != VIDEO_CODE_STATUS.OPERATING_LOCAL:
        return

    mp4_key = video.intercept_video_url
    hash_key = hashlib.md5(str(time.time()).encode("utf8")).hexdigest()
    input_path = os.path.join(settings.VIDEO_CONVERT_PATH, "{}.mp4".format(hash_key))
    output_path = os.path.join(settings.VIDEO_CONVERT_PATH, '{}.webp'.format(hash_key))

    try:
        clipping_video_url = settings.VIDEO_HOST + mp4_key
        res = requests.get(clipping_video_url)

        # 文件存储到本地
        with open(input_path, 'wb') as f:
            f.write(res.content)

        # 使用底层 FFmpeg 库进行转码
        ff = ffmpy.FFmpeg(
            inputs={input_path: None},
            outputs={output_path: settings.VIDEO_FF_ARGS}
        )
        ff.run()

        # 上传webP图片
        video.webp_url = upload_file(output_path)
        video.persistent_clip_status = VIDEO_CODE_STATUS.SUCCESS
        video.save(update_fields=['webp_url', 'persistent_clip_status'])

        # 删除中间数据　
        video_delete(mp4_key)

        # 刷新缓存
        QiniuTool.refresh_qiniu_resource_cache(
            [urljoin(settings.VIDEO_HOST, mp4_key)]
        )

    except:
        logging_exception()
        video.persistent_clip_status = VIDEO_CODE_STATUS.FAIL
        video.save(update_fields=['persistent_clip_status'])

    finally:
        if os.path.exists(input_path):
            os.remove(input_path)
        if os.path.exists(output_path):
            os.remove(output_path)