import json
import time
from urllib.parse import urlencode

import pandas as pd
import requests

from config.url import voice_to_script_task_submit_url, voice_to_script_task_result_url


class GetScriptFromTengXunYunServer(object):
    def __init__(self, logger, db_engine, task_df, task_ids=None):
        self.logger = logger
        self.db_engine = db_engine
        self.task_ids = task_ids
        self.task_df = task_df

    def submit_task(self):
        """
        向腾讯云提交语音转脚本的任务
        task_df: DataFrame columns 包含 signature 和 video_url
        """
        # 1 获取已经被提交过的任务
        sql = f"select signature from tb_asr_result"
        submitted_task_df = pd.read_sql(sql, self.db_engine)

        # 2 需要提交的任务，去掉历史被提交过的任务，防止重复提交浪费服务时长
        to_submit_task_df = self.task_df[~self.task_df.signature.isin(submitted_task_df.signature.values)]
        self.logger.info(f"向腾讯云提交语音转脚本的任务个数为{len(to_submit_task_df)}")

        # 3 发送请求，提交任务
        for index, row in to_submit_task_df.iterrows():
            material_md5 = row['signature']
            material_url = row['video_url']
            request_data = {"signature": material_md5, "url": material_url}
            request_full_path = voice_to_script_task_submit_url + '?' + urlencode(request_data)
            request = requests.post(request_full_path)
            try:
                result = json.loads(request.text)
                self.logger.info(f"素材:{material_md5}, 向腾讯云提交语音转脚本任务的返回信息为{result}")
            except:
                self.logger.error(f"素材:{material_md5}, 向腾讯云提交语音转脚本任务的返回信息为为{ request.text}")

        # 4 获取素材对应的 task_id
        signature_lst = list(self.task_df.signature.values)
        sql = f"select task_id from tb_asr_result where signature " \
              f"in {tuple(signature_lst*2) if len(signature_lst) == 1 else tuple(signature_lst)}"
        task_id_df = pd.read_sql(sql, self.db_engine)
        self.task_ids = list(task_id_df['task_id'].values)

    def get_result(self):
        """
        从腾讯云获取脚本
        每隔1分钟获取一次，直到没有 执行中或者等待执行 的任务为止
        Status Integer 任务状态码，0：任务等待，1：任务执行中，2：任务成功，3：任务失败。
        StatusStr String 任务状态，waiting：任务等待，doing：任务执行中，success：任务成功，failed：任务失败。
        ErrorMsg String 失败原因说明。
        """
        self.logger.info(f"需要获取的脚本个数： {len(self.task_ids)}")
        # 从腾讯云获取脚本的最大重试次数
        retry_upper_cnt = 10
        retry_cnt = 1
        while retry_cnt <= retry_upper_cnt:
            sql = f"select task_id, task_status from tb_asr_result where task_id " \
                  f"in {tuple(self.task_ids * 2) if len(self.task_ids)==1 else tuple(self.task_ids)}" \
                  f" and task_status in (0,1)"
            task_status_df = pd.read_sql(sql, self.db_engine)
            if task_status_df.empty:
                break

            for task_id in task_status_df.task_id.values:
                request_data = {'task_id': task_id}
                request_full_path = voice_to_script_task_result_url + '?' + urlencode(request_data)
                request = requests.post(request_full_path)
                try:
                    result = json.loads(request.text)
                    self.logger.info(f"task_id：{task_id}, 从腾讯云获取脚本返回信息为：{result}")
                except:
                    self.logger.error(f"task_id：{task_id}, 从腾讯云获取脚本返回信息为：{request.text} ")

            if retry_cnt >= 2:
                self.logger.info("从腾讯云获取脚本, 休眠3s，等待腾讯云任务计算完成。")
                time.sleep(3 * 1)

            retry_cnt += 1
