<?php

namespace App\Service;

use App\Exceptions\UserException;
use App\Models\PromptTask;
use App\Models\Task;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class TaskService
{
    public const TYPE_IMG_TO_IMG = 1;  // 图片转图片
    public const TYPE_TEXT_TO_IMG = 2;  // 文字转图片

    public function submit($user_id, array $data = [])
    {
        # task表新增一条记录
        $type = $data['type'] ?? '';
        $prompt = $data['prompt'] ?? '';
        $prompt_img = $data['prompt_img'];
        $prompt_num = $data['prompt_num'] ?? '';
        if (empty($type) || empty($prompt)) {
            throw new UserException('任务类型不能为空');
        }
        # 生成指令数量只能在1-10之间
        if ($prompt_num < 1 || $prompt_num > 10) {
            throw new UserException('生成指令数量只能在1-10之间');
        }

        # 判断类型
        if ($type == self::TYPE_IMG_TO_IMG) {
            # 图片转图片
            if (empty($prompt_img)) {
                throw new UserException('图片不能为空');
            }
        } elseif ($type == self::TYPE_TEXT_TO_IMG) {
            # 文字转图片
        } else {
            throw new UserException('任务类型错误');
        }
        $list = [
            'type' => $type,
            'prompt' => $prompt,
            'prompt_img' => $prompt_img,
            'user_id' => $user_id,
            'prompt_num' => 2,
        ];
        # 保存任务
        $task_id = Task::query()->create($list)->id;
        self::setRedis($task_id, $list);
        # 返回任务id
        return [
            'task_id' => $task_id,
            'prompt_num' => 2
        ];

    }

    /**
     * redis队列插入--这是gpt生成指令的任务
     */
    public function setRedis($task_id, $data = [])
    {
        $data['callback'] = config('common.callback');
        $data['task_id'] = $task_id;
        Redis::rpush('gpt_text_prompt', json_encode($data));
    }


    /**
     * python-gpt任务回调
     */
    public function gpt_callback($data = [])
    {
        $credentials = Arr::only($data, ['prompt', 'user_id', 'task_id', 'prompt_img', 'result_img', 'type']);
        # 必须字段
        $type = $credentials['type'];
        $prompt = $credentials['prompt'] ?? '';
        $prompt = json_decode($prompt);
        $user_id = $credentials['user_id'];
        $task_id = $credentials['task_id'];
        # 可选字段
        $prompt_img = $credentials['prompt_img'] ?? null;
        $result_img = $credentials['result_img'] ?? '';
        # 判断必须字段
        if (empty($type) || empty($prompt) || empty($user_id) || empty($task_id)) {
            throw new UserException('gpt_callback--$user_id,$task_id,$prompt,$type参数错误');
        }
        # 判断$data是否为数组
        if (!is_array($prompt)) {
            throw new UserException('gpt_callback--$prompt参数错误');
        }
        # 循环
        foreach ($prompt as $item) {
            $list = [
                'prompt' => $item,
                'user_id' => $user_id,
                'task_id' => $task_id,
                'prompt_img' => $prompt_img,
                'result_img' => $result_img,
                'type' => $type,
                'callback' => config('common.prompt_callback'),
                'policy' => config('common.policy_callback'),
            ];
            $prompt_id = promptTask::query()->create($list)->id;
            $list['prompt_id'] = $prompt_id;
            # 插入redis,这是自动化的任务
            Redis::rpush('midjourney_prompt', json_encode($list));
        }
        return true;
    }


    /**
     * python - 指令完成-回调
     */
    public function prompt_callback($data = [])
    {
        $credentials = Arr::only($data, ['user_id', 'task_id', 'result_img', 'prompt_id']);
        # 必须字段
        $prompt_id = $credentials['prompt_id'];
        $user_id = $credentials['user_id'];
        $task_id = $credentials['task_id'];
        $result_img = $credentials['result_img'];
        # 判断必须字段
        if (empty($user_id) || empty($task_id) || empty($result_img) || empty($prompt_id)) {
            throw new UserException('指令回调缺少参数');
        }
        # 更新
        $res = PromptTask::query()->where('id', $prompt_id)->where('user_id', $user_id)
            ->where('task_id', $task_id)->update(['result_img' => $result_img,]);
        #
        $list = [
            'user_id' => $user_id,
            'task_id' => $task_id,
            'prompt_id' => $prompt_id,
            'result_img' => $result_img,
            'callback' => config('common.img_download_callback'),
        ];
        # redis队列插入任务--转存图片
        Redis::rpush('discord_img_download', json_encode($list));
        return true;
    }

    /**
     * python - 下载图片完成-回调
     */
    public
    function img_download_callback($data = [])
    {
        $credentials = Arr::only($data, ['prompt_id', 'result_img', 'message']);
        # 必须字段
        $prompt_id = $credentials['prompt_id'] ?? '';
        $message = $credentials['message'] ?? '';
        $result_img = $credentials['result_img'] ?? '';
        # 判断必须字段
        if (empty($prompt_id)) {
            throw new UserException('参数错误');
        }
        # 获取任务
        $task = PromptTask::query()->where('id', $prompt_id)->first();
        if ($task) {
            # 图片不存在则不更新图片
            if ((empty($result_img) || $result_img == '') && $message) {
                # 消息字段
                $old_message = $task->message ?? '';
                $task->update([
                    'message' => $old_message . ',' . $message,
                ]);
            } else if ($result_img) {
                Log::info('更新图片22');
                # 更新
                $task->update([
                    'result_img' => $result_img,
                    'result_img_status' => 1,
                ]);
            }
        }


        return true;
    }

    /**
     * 轮询接口
     */
    public
    function task_callback($user_id, $data = [])
    {
        $credentials = Arr::only($data, ['task_id']);
        # 必须字段
        $task_id = $credentials['task_id'];
        # 判断必须字段
        if (empty($task_id)) {
            Log::error('轮询接口-缺少task_id');
            return false;
        }
        # 查询所有
        $res = PromptTask::query()->where('user_id', $user_id)->where('task_id', $task_id)
            ->where('result_img_status', 1)->get();

        $list = [];
        foreach ($res as $item) {
            $list[] = [
                'img' => $item->result_img,
                'id' => $res->id,
                'split_img' => ''
            ];
        }
        return $list;
    }

    /**
     * 创建切割图片任务
     */
    public
    function create_split_img_task($user_id, $data = [])
    {
        $credentials = Arr::only($data, ['prompt_id', 'cut_id']);
        # 必须字段
        $prompt_id = $credentials['prompt_id'];
        $cut_id = $credentials['cut_id'];
        # 判断必须字段
        if (empty($prompt_id) || empty($cut_id)) {
            throw new UserException(1, '没有这个任务');
        }
        # 找到prompt_id
        $prompt = PromptTask::query()->where('id', $prompt_id)->first();
        if (empty($prompt)) {
            throw new UserException(1, '没有这个任务');
        }
        # 更新
        $prompt->update([
            'cut_id' => $cut_id,
        ]);
        # 添加redis任务
        $list = [
            'prompt_id' => $prompt_id,
            'result_img' => $prompt->result_img,
            'cut_id' => $cut_id,
            'callback' => config('common.split_img_callback'),
        ];
        Redis::rpush('discord_img_split', json_encode($list));
        return [
            'prompt_id' => $prompt_id,
        ];
    }

    /**
     * 图片切割回调
     */
    public function split_callback($data = [])
    {
        $credentials = Arr::only($data, ['cut_img', 'prompt_id']);
        $cut_img = $data['cut_img'] ?? '';
        $prompt_id = $data['prompt_id'] ?? '';
        if (empty($prompt_id) || empty($cut_img)) {
            throw new UserException(1, '缺少必须字段');
        }
        $res = PromptTask::query()->where('id', $prompt_id)->first();
        if ($res) {
            # 更新
            $res = PromptTask::query()->where('id', $prompt_id)->update([
                'cut_img' => $cut_img,
                'cut_status' => 1,
            ]);
        } else {
            throw new UserException(1, '没有这个任务');
        }
        return '';

    }

    /**
     * 轮询获取切割后的图片
     */
    public function IntervalSplitImg($data = [])
    {
        $credentials = Arr::only($data, ['prompt_id']);
        $prompt_id = $credentials['prompt_id'] ?? '';
        if (empty($prompt_id)) {
            throw new UserException(1, '没有这个任务');
        }
        # 查询
        $res = PromptTask::query()->where('id', $prompt_id)->first();
        if (empty($res)) {
            throw new UserException(1, '没有这个任务');
        }
        if ($res->cut_status == 1) {
            return [
                'cut_img' => $res->cut_img,
                'id' => $res->id,
            ];
        }
        return [];
    }
}
