# -*- coding: UTF-8 -*-
"""
>>> python django_manage.py video_renew_webp
"""
import datetime
import json
import os
import threading
import time
import hashlib
from concurrent.futures import ProcessPoolExecutor
from urllib.parse import urljoin

import ffmpy
import requests
from django.core.management import BaseCommand
from django.conf import settings

from gm_types.gaia import VIDEO_CODE_STATUS, QINIU_VIDEO_HANDLE_STATUS_CODE
from gm_upload import video_clipping, upload_file, video_delete
from gm_upload.utils.qiniu_tool import QiniuTool

from talos.models.tractate import TractateVideo, Tractate
from talos.tasks.tractate import (
    set_tractate_video_clipping_to_video,
    check_tractate_video_clipping_is_finish,
    set_tractate_video_webp_pic
)
from utils.common import big_qs_iter
from utils.rpc import logging_exception


class VideoClip2Webp(object):
    def __init__(self, qiniu_video_key):
        self.qiniu_video_key = qiniu_video_key

    def clip_video(self):
        hash_key = hashlib.md5(str(time.time()).encode("utf8")).hexdigest()
        pid = video_clipping(
            self.qiniu_video_key,
            new_filename='{}_clip.mp4'.format(hash_key),
            video_type='mp4',
            water_mark_url=None,
            start_time=3,
            # water_mark_url=settings.WATER_MARK_URL_FOR_VIDEO
        )
        print(pid)
        return pid

    def get_clip_video_status(self, pid):
        result = json.loads(requests.get('{}{}'.format(
            settings.QINIU_VIDEO_INQUIRE_HOST,
            pid,
        )).text)
        print(result)
        # 状态码0成功，1等待处理，2正在处理，3处理失败，4通知提交失败。
        # 如果请求失败，返回包含如下内容的JSON字符串{"error":   "<ErrMsg    string>"}
        code = result.get('code')
        error = result.get('error', '')
        if error or code not in (
                QINIU_VIDEO_HANDLE_STATUS_CODE.SUCCESS,
                QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL
            ):
            return None
        return result

    def check_clip_video_status(self, pid):
        if not pid:
            return ''
        i = 0
        while True:
            print('waiting: (%s)' % i)
            i += 1
            time.sleep(2)
            result = self.get_clip_video_status(pid)
            if result:
                break

        code = result.get('code')
        if code == QINIU_VIDEO_HANDLE_STATUS_CODE.PROCESSING_FAIL:
            return ''

        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)])
            return mp4_key
        else:
            return ''

    def convert_clip_video_to_webp(self, mp4_key):
        if not mp4_key:
            return ''
        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图片
            webp_url = upload_file(output_path)
            # 删除中间数据　
            video_delete(mp4_key)
            # 刷新缓存
            QiniuTool.refresh_qiniu_resource_cache(
                [urljoin(settings.VIDEO_HOST, mp4_key)]
            )
        except:
            logging_exception()
            webp_url = ''
        finally:
            if os.path.exists(input_path):
                os.remove(input_path)
            if os.path.exists(output_path):
                os.remove(output_path)
        return webp_url

    def do_clip_to_webp(self):
        pid = self.clip_video()
        mp4_key = self.check_clip_video_status(pid)
        webp_url = self.convert_clip_video_to_webp(mp4_key)
        return webp_url


class TractateVideoWebP(object):
    def __init__(self, video):
        self.video = video
        self.clip_obj = VideoClip2Webp(self.video.raw_video_url)

    def process(self):
        webp_url = self.clip_obj.do_clip_to_webp()
        if webp_url:
            self.video.webp_url = webp_url
            self.video.persistent_clip_status = VIDEO_CODE_STATUS.SUCCESS
            self.video.save(update_fields=['webp_url', 'persistent_clip_status'])

    @classmethod
    def run_all(cls):
        print("tractate_video start-----{}".format(time.time()))

        with ProcessPoolExecutor(max_workers=4) as ex:
            videos = TractateVideo.objects.all()
            for _video in big_qs_iter(videos, fetch_num=100, trace=True):
                if not Tractate.objects.filter(id=_video.tractate_id, content_level__gt=3).exists():
                    continue
                _webp_url = _video.webp_url
                dt_str = _webp_url[-21: -11]
                try:
                    dt = datetime.datetime.strptime(dt_str, "%Y/%m/%d")
                except Exception:
                    dt = None
                if dt and dt > datetime.datetime(2020, 10, 28):
                    continue
                print(_video.id, dt)
                _obj = cls(_video)
                # ex.submit(_obj.process)
                _obj.process()

        print("tractate_video end-----{}".format(time.time()))


class Command(BaseCommand):
    """
    为所有已有视频添加webP动图
    """

    def handle(self, *args, **options):
        print('------ starting -----')
        start_time = time.time()
        print("start at: ", start_time)

        # tractate_id = 170680
        # _video = TractateVideo.objects.get(tractate_id=tractate_id)
        # TractateVideoWebP(_video).process()

        TractateVideoWebP.run_all()

        end_time = time.time()
        print("end at: ", end_time)
        print('total use {} s.'.format(end_time - start_time))
        print('Done!')