# -*- coding: utf-8 -*-
import requests
import json
import time
from urllib.parse import urlparse
import os, sys
import cv2

base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_path)
import video_gen
import tos_util
import redis
import random

doubao_api_token = 'Bearer fcc424e5-58af-494d-9683-5787413a26c9'
sora_api_token = 'Bearer ade2547a49722db6375545e4123e2088'
dir = '/Users/yaowentong/Desktop/video/'

redis_client = redis.Redis(host='172.16.0.24', port=6379, db=8, password='aiyingli@@123', socket_timeout=10,
                           decode_responses=True)
# (标题背景颜色，标题文字颜色，正文文字颜色，标题透明度，正文透明度,描边颜色,描边大小)
list = [
    ((255, 213, 75), '#000000', '#FFDE00', 1, 0.2, 'black', 1),  # 标题黄底 黑字 正文黄字
    # (( 255 ,215, 77), '#000000', '#000000',1,1,'black',0), # 标题黄底 黑字 正文黄字
    ((255, 255, 255), '#FEDE01', '#BE3030', 0, 0.2, 'white', 1),  # 标题黄底 黑字 正文黄字
    ((255, 255, 255), '#FEE001', '#FFFFFF', 0, 0.2, 'black', 1),  # 标题黄底 黑字 正文黄字
]


def extract_first_frame(video_path, output_image_path):
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        print(f"无法打开视频文件: {video_path}")
        return False

    ret, frame = cap.read()

    if ret:
        # 保存第一帧为图片（支持格式：.jpg, .png 等）
        cv2.imwrite(output_image_path, frame)
        print(f"第一帧已保存至: {output_image_path}")
    else:
        print("无法读取视频的第一帧")

    # 释放资源
    cap.release()
    return ret


def sora_generate_video(prompt, video_duration, ratio):
    # portrait | landscape
    url = "https://api.kie.ai/api/v1/jobs/createTask"

    payload = json.dumps({
        "model": "sora-2-text-to-video-stable",
        "input": {
            "prompt": prompt,
            "aspect_ratio": ratio,
            "n_frames": str(video_duration),
            "remove_watermark": True
        }
    })
    headers = {
        'Authorization': sora_api_token,
        'Content-Type': 'application/json'
    }

    try:
        response = requests.request("POST", url, headers=headers, data=payload)
        print(response.text)
        return response.json().get('data').get('taskId')
    except Exception as err:
        print(f'{err}')


def sora_search_video(task_id):
    url = f"https://api.kie.ai/api/v1/jobs/recordInfo?taskId={task_id}"

    payload = {}
    headers = {
        'Authorization': sora_api_token
    }

    response = requests.request("GET", url, headers=headers, data=payload)

    try:
        return response.json()
    except Exception as err:
        print(f'{err}')


def sora_get_video_url(task_id: str, file_name, max_retries: int = 100) -> str:
    retry_count = 0

    while retry_count < max_retries:
        try:
            # 发送请求查询任务状态
            task_data = sora_search_video(task_id)['data']

            # 状态判断
            if task_data["state"] == "success":
                print("任务成功，获取视频链接")
                return json.loads(task_data['resultJson']).get('resultUrls')[0]  # 返回视频链接
            # todo
            elif task_data["state"] == "generating" or task_data["state"] == "waiting":
                retry_count += 1
                wait_time = 3
                print(f"任务运行中，{wait_time}秒后重试（第{retry_count}/{max_retries}次）")
                time.sleep(wait_time)
            else:
                if task_data["state"] == 'fail' and task_data["failCode"] == 500:
                    json_url = f'dso/ai_gen/video/{file_name}/info.json'
                    tos_util.put_string_to_tos(f'{json_url}',
                                               ["异常：网络异常，请稍后再试"])
                else:
                    json_url = f'dso/ai_gen/video/{file_name}/info.json'
                    tos_util.put_string_to_tos(f'{json_url}',
                                               ["异常：你输入的文字不符合制作规则，请修改后重试"])
                print(f"任务异常，状态：{task_data['state']} task：{task_id}")
                # 处理其他异常状态（如failed）
                raise Exception(f"任务异常，状态：{task_data['state']} task：{task_id}")
        except requests.exceptions.RequestException as e:
            raise Exception(f"请求失败：{str(e)}")
    json_url = f'dso/ai_gen/video/{file_name}/info.json'
    tos_util.put_string_to_tos(f'{json_url}', ["异常：网络异常，请稍后再试"])


def doubao_generate_video(text, duration, ratio):
    url = "https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks"

    payload = json.dumps({
        "model": "doubao-seedance-1-0-pro-250528",
        "content": [
            {
                "type": "text",
                "text": f"{text}  --resolution 720p  --duration {duration} --camerafixed false --watermark false --ratio {ratio}"
            }
        ]
    })
    headers = {
        'Authorization': doubao_api_token,
        'Content-Type': 'application/json'
    }
    try:
        response = requests.request("POST", url, headers=headers, data=payload)
        print(response.text)
        return response.json().get('id')
    except Exception as err:
        print(f'{err}')


def doubao_search_video(task_id):
    url = f"https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks/{task_id}"

    payload = ""
    headers = {
        'Authorization': doubao_api_token,
        'Content-Type': 'application/json'
    }

    response = requests.request("GET", url, headers=headers, data=payload)
    try:
        return response.json()
    except Exception as err:
        print(f'{err}')


def doubao_get_video_url(task_id: str, file_name, max_retries: int = 500) -> str:
    doubao_search_video(task_id)
    retry_count = 0

    while retry_count < max_retries:
        try:
            # 发送请求查询任务状态
            task_data = doubao_search_video(task_id)

            # 状态判断
            if task_data["status"] == "succeeded":
                print("任务成功，获取视频链接")
                print(task_data["content"]["video_url"])
                return task_data["content"]["video_url"]  # 返回视频链接
            elif task_data["status"] == "running" or "queued":
                retry_count += 1
                wait_time = 3
                print(f"任务运行中，{wait_time}秒后重试（第{retry_count}/{max_retries}次）")
                time.sleep(wait_time)
            else:
                json_url = f'dso/ai_gen/video/{file_name}/info.json'
                tos_util.put_string_to_tos(f'{json_url}',
                                           [])
                print(f"任务异常，状态：{task_data['status']} task：{task_id}")
                # 处理其他异常状态（如failed）
                raise Exception(f"任务异常，状态：{task_data['status']} task：{task_id}")
        except requests.exceptions.RequestException as e:
            raise Exception(f"请求失败：{str(e)}")


def download_video(video_url: str, save_dir: str = "./downloads", file_name: str = None) -> None:
    if save_dir and not os.path.exists(save_dir):
        os.makedirs(save_dir, exist_ok=True)

    if not file_name:
        parsed_url = urlparse(video_url)
        file_name = os.path.basename(parsed_url.path)
        # 确保文件名以.mp4结尾（防止URL特殊情况）
        if not file_name.endswith(".mp4"):
            file_name += ".mp4"

    save_path = os.path.join(save_dir, file_name)

    try:
        # 2. 发送请求获取视频流（stream=True避免一次性加载到内存）
        response = requests.get(video_url, stream=True, timeout=30)
        response.raise_for_status()  # 若HTTP状态码非200（如404/500），抛出异常

        # 4. 写入文件（按字节流写入，支持大文件）
        with open(save_path, "wb") as f:
            for chunk in response.iter_content(chunk_size=1024 * 1024):  # 每次读取1MB
                if chunk:  # 过滤空块
                    f.write(chunk)

        print(f"\n下载完成！视频已保存至：{save_path}")

    except requests.exceptions.RequestException as e:
        # 下载失败时删除不完整文件
        if os.path.exists(save_path):
            os.remove(save_path)
        raise Exception(f"视频下载失败：{str(e)}")


def gen_16_9(task_id, title, bottom_text_content, file_name, color_list):
    video_gen.gen_16_9_video(
        input_video=f"{dir}{file_name}/{task_id}.mp4",
        output_video=f"{dir}{file_name}/{task_id}_result.mp4",
        # 文字内容
        text_content=title,
        text_content_color=color_list[1],
        title_overlay_opacity=color_list[3],
        bottom_overlay_opacity=color_list[4],
        overlay_color=color_list[0],
        font_size=90,
        vertical_font_size=20,
        bottom_font_size=50,
        bottom_stroke_color=color_list[5],
        bottom_stroke_width=color_list[6],
        bottom_text_content=bottom_text_content,
        bottom_text_content_color=color_list[2],
        background_music=f'{dir}Pond.mp3'
    )


def gen_9_16(task_id, title, bottom_text_content, file_name, color_list):
    font_size = 90
    if len(title) > 9:
        title = title[:6] + '\n' + title[6:]
        font_size = 60
    video_gen.gen_9_16_video(
        input_video=f"{dir}{file_name}/{task_id}.mp4",
        output_video=f"{dir}{file_name}/{task_id}_result.mp4",
        # 文字内容
        text_content=title,
        text_content_color=color_list[1],
        title_overlay_opacity=color_list[3],
        bottom_overlay_opacity=color_list[4],
        overlay_color=color_list[0],
        font_size=font_size,
        vertical_font_size=25,
        bottom_font_size=80,
        bottom_stroke_color=color_list[5],
        bottom_stroke_width=color_list[6],
        bottom_text_content=bottom_text_content,
        bottom_text_content_color=color_list[2],
        background_music=f'{dir}Pond.mp3'
    )


def gen_video_process(model, video_text, video_duration, video_ratio, title, bottom_text_content, file_name):
    color_list = random.choice(list)
    if model == 1:
        task_id = doubao_generate_video(video_text, video_duration, video_ratio)
        video_url = doubao_get_video_url(task_id, file_name)
        download_video(video_url, f'{dir}{file_name}/', f'{task_id}.mp4')
        if video_ratio == '16:9':
            gen_16_9(task_id, title, bottom_text_content, file_name, color_list)
        elif video_ratio == '9:16':
            gen_9_16(task_id, title, bottom_text_content, file_name, color_list)
        else:
            raise ValueError(f"不支持的比例类型: {video_ratio}")
    elif model == 2:
        if video_ratio == '16:9':
            task_id = sora_generate_video(video_text, video_duration, 'landscape')
            video_url = sora_get_video_url(task_id, file_name)
            download_video(video_url, f'{dir}{file_name}/', f'{task_id}.mp4')
            gen_16_9(task_id, title, bottom_text_content, file_name, color_list)
        elif video_ratio == '9:16':
            task_id = sora_generate_video(video_text, video_duration, 'portrait')
            video_url = sora_get_video_url(task_id, file_name)
            download_video(video_url, f'{dir}{file_name}/', f'{task_id}.mp4')
            gen_9_16(task_id, title, bottom_text_content, file_name, color_list)
        else:
            raise ValueError(f"不支持的比例类型: {video_ratio}")
    else:
        raise ValueError(f"不支持的模型类型: {model}")

    mp4_url = f'dso/ai_gen/video/{file_name}/{file_name}.mp4'
    mp4_url_nc = f'dso/ai_gen/video/{file_name}/{file_name}_nc.mp4'
    json_url = f'dso/ai_gen/video/{file_name}/info.json'
    # 上传视频
    tos_util.put_video(mp4_url,
                       f'{dir}{file_name}/{task_id}_result.mp4')
    tos_util.put_video(mp4_url_nc,
                       f'{dir}{file_name}/{task_id}.mp4')
    # 提取first frame
    extract_first_frame(f'{dir}{file_name}/{task_id}.mp4', f'{dir}{file_name}/{task_id}_nc.jpg')
    extract_first_frame(f'{dir}{file_name}/{task_id}_result.mp4', f'{dir}{file_name}/{task_id}.jpg')

    jpg_url = f'dso/ai_gen/video/{file_name}/{file_name}.jpg'
    jpg_url_nc = f'dso/ai_gen/video/{file_name}/{file_name}_nc.jpg'
    # 上传first frame
    tos_util.put_video(jpg_url_nc,
                       f'{dir}{file_name}/{task_id}_nc.jpg')
    tos_util.put_video(jpg_url,
                       f'{dir}{file_name}/{task_id}.jpg')
    # 上传json
    tos_util.put_string_to_tos(f'{json_url}',
                               [f'https://static2.douchacha.com/{mp4_url}',
                                f'https://static2.douchacha.com/{mp4_url_nc}'])


if __name__ == '__main__':

    # task = redis_client.rpop('dso_video_gen_task')
    #
    # try:
    #     task_json = json.loads(task)
    #     model = task_json['model']
    #     video_text = task_json['video_text']
    #     video_duration = task_json['video_duration']
    #     video_ratio = task_json['video_ratio']
    #     title = task_json['title']
    #     bottom_text_content = task_json['bottom_text_content']
    #     file_name = task_json['task_id']
    #     gen_video_process(model, video_text, video_duration, video_ratio, title, bottom_text_content, file_name)
    # except Exception as err:
    #     print(f'{err}')
    while 1:

        print(doubao_search_video('cgt-20260409205146-hpnpn'))
        time.sleep(3)
    # # print(sora_search_video('dfb37c95397b88e85b48b055a5ccccbb'))
    #
    # # 9: 16 7行7字 标题6个字不用换行 411300
    # # 16：9 标题12字以内不用处理
    # task_json = {"bottom_text_content": "\n天安门庄严雄伟\n天安门庄严雄伟\n天安门庄严雄伟 ", "creationType": "VIDEO",
    #              "keyword": "天安门", "model": 2, "task_id": "100222822222222611",
    #              "title": "晨跑好还是夜跑好", "video_duration": 10, "video_ratio": "9:16",
    #              "video_text": "晨跑好还是夜跑好 俩个人在跑步对比 一个是白天一个是黑夜"}
    # try:
    #     # task_json = json.loads(task)
    #     model = task_json['model']
    #     video_text = task_json['video_text']
    #     video_duration = task_json['video_duration']
    #     video_ratio = task_json['video_ratio']
    #     title = task_json['title']
    #     bottom_text_content = task_json['bottom_text_content']
    #     file_name = task_json['task_id']
    #     gen_video_process(model, video_text, video_duration, video_ratio, title, bottom_text_content, file_name)
    # except Exception as err:
    #     # redis_client.rpush('dso_video_gen', task)
    #     print(f'{err}')

