<?php

namespace App\Services\Timbre;

use App\Consts\ErrorConst;
use App\Facade\Site;
use App\Libs\Utils;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use OSS\Core\OssException;
use OSS\OssClient;

class TimbreService
{

    public function __construct() {

    }

    public function addCategory($data) {
        $category_name = getProp($data, 'category_name');
        $pid = getProp($data, 'pid');
        if ($pid === '') Utils::throwError('20003:参数异常');

        $category = DB::table('mp_timbre_categories')->where('category_name', $category_name)->first();
        if ($category) {
            return Utils::throwError('20003:该分类已存在');
        }

        if ($pid) {
            $category = DB::table('mp_timbre_categories')->where('id', $pid)->first();
            if (!$category) {
                return Utils::throwError('20003:该分类不存在');
            }
        }

        $category_id = DB::table('mp_timbre_categories')->insertGetId([
            'category_name' => $category_name,
            'pid' => $pid,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
        if (!$category_id) Utils::throwError('20003:添加失败');
        return [
            'category_id'       => $category_id,
            'category_name'     => $category_name,
            'pid'               => $pid,
        ];
    }

    public function editCategory($data) {
        $category_id = getProp($data, 'category_id');
        $category_name = getProp($data, 'category_name');

        $category = DB::table('mp_timbre_categories')->where('id', $category_id)->first();
        if (!$category) {
            return Utils::throwError('20003:该分类不存在');
        }

        $category = DB::table('mp_timbre_categories')->where('category_name', $category_name)->first();
        if ($category && $category->id != $category_id) {
            return Utils::throwError('20003:该分类已存在');
        }

        return DB::table('mp_timbre_categories')->where('id', $category_id)->update([
            'category_name' => $category_name,
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }

    public function getCategoryList($data) {
        $category_type = getProp($data, 'category_type', 1);
        $category_id = getProp($data, 'category_id');
        $category_name = getProp($data, 'category_name');
        $page = getProp($data, 'page', 1);
        $per_page = getProp($data, 'pageSize', 15);
        $pid = getProp($data, 'pid');

        $query = DB::table('mp_timbre_categories')->where('is_enable', 1)->select('*');
        switch ($category_type) {
            case 1:
                $query->where('pid', 0);
                break;
            case 2:
                $query->where('pid', $pid);
                break;
            case 3:
                $query->where('pid', $pid);
                break;
            default:
                break;
        }

        if ($category_id) {
            $query->where('id', $category_id);
        }
        if ($category_name) {
            $query->where('category_name', 'like', "%{$category_name}%");
        }

        return $query->orderBy('id')->paginate($per_page);
    }

    public function getTimbreList($data) {
        $timbre_name = getProp($data, 'voice_name');
        $language = getProp($data, 'language');
        $status = getProp($data, 'status');
        $dialect = getProp($data, 'dialect');
        $page = getProp($data, 'page', 1);
        $per_page = getProp($data, 'pageSize', 15);

        $query = DB::table('mp_timbres')->where('is_enabled', 1)->select('*');

        if ($timbre_name) {
            $query->where('timbre_name', 'like', "%{$timbre_name}%");
        }

        if ($language) {
            $query->where('language', 'like', "%{$language}%");
        }

        if ($dialect) {
            $query->where('dialect', $dialect);
        }

        $result = $query->orderBy('id')->paginate($per_page);

        return $result;
    }

    public function timbreCategories($data) {
        $categories = DB::table('mp_timbre_categories')->where('is_enable', 1)->select('id as category_id', 'category_name', 'pid')->get()->map(function ($value) {
            return (array)$value;
        })->toArray();

        $result = buildCategoryTree($categories, 0);
        return $result;
    }

    public function editTimbre($data) {
        $timbre_id = getProp($data, 'voice_id');
        $timbre = DB::table('mp_timbres')->where('id', $timbre_id)->first();
        if (!$timbre) {
            return Utils::throwError('20003:该音色不存在');
        }

        $update_data = [
            'updated_at'    => date('Y-m-d H:i:s'),
        ];

        if (getProp($data, 'first_category_id')) {
            $update_data['first_category_id'] = getProp($data, 'first_category_id');
            $update_data['first_category_name'] = DB::table('mp_timbre_categories')->where('id', getProp($data, 'first_category_id'))->value('category_name');
        }
        if (getProp($data, 'second_category_id')) {
            $update_data['second_category_id'] = getProp($data, 'second_category_id');
            $update_data['second_category_name'] = DB::table('mp_timbre_categories')->where('id', getProp($data, 'second_category_id'))->value('category_name');
        }
        if (getProp($data, 'third_category_id')) {
            $update_data['third_category_id'] = getProp($data, 'third_category_id');
            $update_data['third_category_name'] = DB::table('mp_timbre_categories')->where('id', getProp($data, 'third_category_id'))->value('category_name');
        }
        if (getProp($data, 'label')) $update_data['label'] = getProp($data, 'label');

        return DB::table('mp_timbres')->where('id', $timbre_id)->update($update_data);
    }

    public function getAllBooks($data) {
        $bid = getProp($data, 'bid');
        $book_name = getProp($data, 'book_name');

        $query = $query = DB::table('books as b')->leftJoin('book_configs as bc', 'b.id', '=', 'bc.bid')
        ->where('b.size', '<', 30000)->where('b.status', 1)
        ->whereIn('bc.cp_source', ['ycsd', 'yqsd'])->select('bc.bid', 'bc.book_name');
        if ($bid) {
            $query->where('bc.bid', $bid);
        }

        if ($book_name) {
            $query->where('bc.book_name', 'like', "%{$book_name}%");
        }

        return $query->orderBy('bc.bid', 'desc')->get()->map(function($value) {
            return (array)$value;
        })->toArray();
    }

    public function timbreGroupList($data) {
        $group_name = getProp($data, 'group_name');
        $label = getProp($data, 'label');
        $page = getProp($data, 'page', 1);
        $per_page = getProp($data, 'pageSize', 15);

        $query = DB::table('mp_timbre_groups')->select('*');

        if ($group_name) {
            $query->where('group_name', 'like', "%{$group_name}%");
        }

        if ($label) {
            $query->where('label', 'like', $label);
        }

        return $query->orderBy('id')->paginate($per_page);
    }

    public function addTimbreGroup($data) {
        $group_name = getProp($data, 'group_name');
        $male_lead_voice_name = getProp($data, 'male_lead_voice_name');
        $male_lead_voice_type = getProp($data, 'male_lead_voice_type');
        $female_lead_voice_name = getProp($data, 'female_lead_voice_name');
        $female_lead_voice_type = getProp($data, 'female_lead_voice_type');
        $narration_voice_name = getProp($data, 'narration_voice_name');
        $narration_voice_type = getProp($data, 'narration_voice_type');
        if (!$group_name || !$male_lead_voice_type || !$female_lead_voice_type || !$narration_voice_type) Utils::throwError('20003:参数错误');
        $label = getProp($data, 'label');
        $other_roles = getProp($data, 'other_roles');
        if (DB::table('mp_timbre_groups')->where('group_name', $group_name)->value('id')) Utils::throwError('20003:该音色组已存在');

        return DB::table('mp_timbre_groups')->insert([
            'group_name'                => $group_name,
            'male_lead_voice_name'      => $male_lead_voice_name,
            'male_lead_voice_type'      => $male_lead_voice_type,
            'female_lead_voice_name'    => $female_lead_voice_name,
            'female_lead_voice_type'    => $female_lead_voice_type,
            'narration_voice_name'      => $narration_voice_name,
            'narration_voice_type'      => $narration_voice_type,
            'label'                     => $label,
            'other_roles'               => $other_roles,
            'created_at'                => date('Y-m-d H:i:s'),
            'updated_at'                => date('Y-m-d H:i:s'),
        ]);
    }

    public function editTimbreGroup($data) {
        $group_id = getProp($data, 'group_id');
        $group_name = getProp($data, 'group_name');
        $male_lead_voice_name = getProp($data, 'male_lead_voice_name');
        $male_lead_voice_type = getProp($data, 'male_lead_voice_type');
        $female_lead_voice_name = getProp($data, 'female_lead_voice_name');
        $female_lead_voice_type = getProp($data, 'female_lead_voice_type');
        $narration_voice_name = getProp($data, 'narration_voice_name');
        $narration_voice_type = getProp($data, 'narration_voice_type');
        if (!$group_id || !$group_name || !$male_lead_voice_type || !$female_lead_voice_type || !$narration_voice_type) Utils::throwError('20003:参数错误');
        $label = getProp($data, 'label');
        $other_roles = getProp($data, 'other_roles');
        $tmp_group_id = DB::table('mp_timbre_groups')->where('group_name', $group_name)->value('id');
        if ($tmp_group_id && $tmp_group_id != $group_id) Utils::throwError('20003:该音色组已存在');

        return DB::table('mp_timbre_groups')->where('id', $group_id)->update([
            'group_name'                => $group_name,
            'male_lead_voice_name'      => $male_lead_voice_name,
            'male_lead_voice_type'      => $male_lead_voice_type,
            'female_lead_voice_name'    => $female_lead_voice_name,
            'female_lead_voice_type'    => $female_lead_voice_type,
            'narration_voice_name'      => $narration_voice_name,
            'narration_voice_type'      => $narration_voice_type,
            'label'                     => $label,
            'other_roles'               => $other_roles,
            'updated_at'                => date('Y-m-d H:i:s'),
        ]);
    }

    public function emotionGroupList($data) {
        $id = getProp($data, 'group_id');
        $group_name = getProp($data, 'group_name');
        $voice_type = getProp($data, 'voice_type');
        $page = getProp($data, 'page', 1);
        $per_page = getProp($data, 'pageSize', 15);

        $query = DB::table('mp_emotion_groups')->where('is_enabled', 1)->select('*');

        if ($group_name) {
            $query->where('group_name', 'like', "%{$group_name}%");
        }

        if ($id) {
            $query->where('id', $id);
        }

        if ($voice_type) {
            $query->where('voice_type', $voice_type);
        }

        return $query->orderBy('id')->paginate($per_page);
    }

    public function addEmotionGroup($data) {
        $group_name = getProp($data, 'group_name');
        if (DB::table('mp_emotion_groups')->where('group_name', $group_name)->value('id')) Utils::throwError('20003:该组名已存在');
        // 获取所有情感
        $emotion_list = DB::table('mp_emotion_list')->where('is_enabled', 1)->pluck('emotion_name', 'emotion_code')->toArray();
        $emotion_list = array_flip($emotion_list);

        // 获取音色支持情感
        $timbre_emotion = DB::table('mp_timbres')->where('timbre_type', getProp($data, 'voice_type'))->value('emotion');
        $timbre_emotion = explode('，', $timbre_emotion);
        $emotion = getProp($data, 'emotion');
        if (!in_array($emotion, $timbre_emotion)) $emotion = '中性';
        $emotion_type = isset($emotion_list[$emotion]) ? $emotion_list[$emotion] : 'neutral';

        // 给一个默认文案
        $text = '试听这段由专业团队打造的声音杰作。从角色塑造到环境音效，每个元素都经过反复推敲，只为给你带来最完美的听觉体验。';
        $list = [
            'group_name'    => $group_name,
            // 'text'          => trim(getProp($data, 'text')),
            'text'          => $text,
            'emotion'       => $emotion,
            'emotion_type'  => $emotion_type,
            'voice_type'    => getProp($data, 'voice_type'),
            'voice_name'    => getProp($data, 'voice_name'),
            'speed_ratio'   => getProp($data, 'speed_ratio', 0),
            'loudness_ratio'=> getProp($data, 'loudness_ratio', 0),
            'emotion_scale' => getProp($data, 'emotion_scale', 4),
            'pitch'         => getProp($data, 'pitch', 0),
            'generate_status' => '制作中',
            'error_msg'     => '',
            'created_at'    => date('Y-m-d H:i:s'),
            'updated_at'    => date('Y-m-d H:i:s')
        ];

        $id = DB::table('mp_emotion_groups')->insertGetId($list);
        $boolen = $id ? true : false;

        if ($boolen) {
            $boolen = false;
            $client = new Client(['timeout' => 300, 'verify' => false]);
            // 根据ID通过API通知合成音频
            // $result = $client->get("http://47.240.171.155:5000/api/emotionGroupTask?taskId={$id}");
            $result = $client->get("http://122.9.129.83:5000/api/emotionGroupTask?taskId={$id}");
            $response = $result->getBody()->getContents();
            $response_arr = json_decode($response, true);
            if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
                $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
                Log::info('火山生成音频失败: '.$error_msg);
                Utils::throwError('20003:火山生成音频失败');
            }
            $boolen = true;
        }

        return $boolen;
    }

    public function editEmotionGroup($data) {
        $group_id = getProp($data, 'group_id');
        $group_name = getProp($data, 'group_name');
        $tmp_group_id = DB::table('mp_emotion_groups')->where('group_name', $group_name)->value('id');
        if ($tmp_group_id && $tmp_group_id != $group_id) Utils::throwError('20003:该音色组已存在');
        // 获取所有情感
        $emotion_list = DB::table('mp_emotion_list')->where('is_enabled', 1)->pluck('emotion_name', 'emotion_code')->toArray();
        $emotion_list = array_flip($emotion_list);

        // 获取音色支持情感
        $timbre_emotion = DB::table('mp_timbres')->where('timbre_type', getProp($data, 'voice_type'))->value('emotion');
        $timbre_emotion = explode('，', $timbre_emotion);
        $emotion = getProp($data, 'emotion');
        if (!in_array($emotion, $timbre_emotion)) $emotion = '中性';
        $emotion_type = isset($emotion_list[$emotion]) ? $emotion_list[$emotion] : 'neutral';

        $list = [
            'group_name'    => $group_name,
            // 'text'          => trim(getProp($data, 'text')),
            'emotion'       => $emotion,
            'emotion_type'  => $emotion_type,
            'voice_type'    => getProp($data, 'voice_type'),
            'voice_name'    => getProp($data, 'voice_name'),
            'speed_ratio'   => getProp($data, 'speed_ratio', 0),
            'loudness_ratio'=> getProp($data, 'loudness_ratio', 0),
            'emotion_scale' => getProp($data, 'emotion_scale', 4),
            'pitch'         => getProp($data, 'pitch', 0),
            'generate_status' => '制作中',
            'error_msg'     => '',
            'updated_at'    => date('Y-m-d H:i:s')
        ];

        $boolen = DB::table('mp_emotion_groups')->where('id', $group_id)->update($list);

        if ($boolen) {
            $boolen = false;
            $client = new Client(['timeout' => 300, 'verify' => false]);
            // 根据ID通过API通知合成音频
            // $result = $client->get("http://47.240.171.155:5000/api/emotionGroupTask?taskId={$group_id}");
            $result = $client->get("http://122.9.129.83:5000/api/emotionGroupTask?taskId={$group_id}");
            $response = $result->getBody()->getContents();
            $response_arr = json_decode($response, true);
            if (!isset($response_arr['code']) || (int)$response_arr['code'] !== 0) {
                $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
                Log::info('火山生成音频失败: '.$error_msg);
                Utils::throwError('20003:火山生成音频失败');
            }
            $boolen = true;
        }

        return $boolen;
    }

    public function delEmotionGroup($data) {
        $group_id = getProp($data, 'group_id');
        $url = DB::table('mp_emotion_groups')->where('id', $group_id)->value('audio_url');
        
        $boolen = DB::table('mp_emotion_groups')->where('id', $group_id)->update([
            'is_enabled' => 0,
            'updated_at'    => date('Y-m-d H:i:s')
        ]);

        if ($boolen && $url) {
            $boolen = false;
            $encode_url = urlencode($url);
            $client = new Client(['timeout' => 300, 'verify' => false]);
            // 根据ID通过API通知合成音频
            // $result = $client->get("http://47.240.171.155:5000/api/fileDelete?url={$encode_url}");
            $result = $client->get("http://122.9.129.83:5000/api/fileDelete?url={$encode_url}");
            $response = $result->getBody()->getContents();
            $response_arr = json_decode($response, true);
            Log::info('火山删除音频返回: '.$response);
            if (!isset($response_arr['status']) || (int)$response_arr['status'] !== 0) {
                $error_msg = isset($response_arr['msg']) ? $response_arr['msg'] : '未知错误';
                Log::info('火山删除音频失败: '.$error_msg);
                Utils::throwError('20003:火山删除音频失败');
            }
            $boolen = true;
        }

        return $boolen;
    }
}
