<?php

namespace App\Services\Smm;

use App\Services\Contracts\SmmPlatformInterface;
use Carbon\Carbon;
use Google_Client;
use Google_Service_YouTube;
use Google_Service_YouTube_Video;
use Google_Service_YouTube_VideoSnippet;
use Google_Service_YouTube_VideoStatus;
use Google_Http_MediaFileUpload;
use Illuminate\Http\Request;
use OSS\OssClient;
use OSS\Core\OssException;
use Illuminate\Support\Facades\Log;


class YoutubeService implements SmmPlatformInterface
{
    protected Google_Client $client;
    protected string $redirectUri;

    protected array $configData;

    public function __construct(array $configData)
    {
        $this->configData = $configData;
        $this->client = new Google_Client();
        $this->client->setClientId(env('SSM_YOUTUBE_CLIENT_ID'));
        $this->client->setClientSecret(env('SSM_YOUTUBE_CLIENT_SECRET'));
        $this->client->setRedirectUri(env('DIST_SITE_URL').'/dist/callback/youtube');
        $this->client->setScopes([
            Google_Service_YouTube::YOUTUBE_UPLOAD,
            Google_Service_YouTube::YOUTUBE,
        //    Google_Service_YouTube::YOUTUBE_FORCE_SSL,
        //    Google_Service_YouTube::YOUTUBE_READONLY,
        //    Google_Service_YouTube::YOUTUBEPARTNER,
        //    Google_Service_YouTube::YOUTUBEPARTNER_CHANNEL_AUDIT
        ]);

        $this->client->setAccessType('offline');
        $this->client->setPrompt('consent');
        $this->client->setDeveloperKey(env('SSM_YOUTUBE_DEV_KEY'));
    }

    public function login()
    {
        try {
            return ['status' => true, 'data' => ['url' => $this->client->createAuthUrl()]];
        } catch (\Exception $e) {
            return ['status' => false, 'data' => 'Failed to generate login URL: '.$e->getMessage()];
        }
    }

    public function loginCallback(Request $request)
    {
        try {
            $code = $request->input('code');
            if (!$code) {
                return ['status' => false, 'data' => 'Authorization code not found'];
            }
            $token = $this->client->fetchAccessTokenWithAuthCode($code);
            if (isset($token['error'])) {
                return ['status' => false, 'data' => $token['error_description'] ?? 'Failed to exchange authorization code'];
            }
            $this->client->setAccessToken($token);
            $youtube = new Google_Service_YouTube($this->client);
            $channelResponse = $youtube->channels->listChannels('snippet', ['mine' => true]);

            return [
                'status' => true,
                'data' => [
                    'accessToken' => $token['access_token'],
                    'refreshToken' => $token['refresh_token'] ?? '',
                    'accessToken_expiresAt' => Carbon::now()->addSeconds($token['expires_in']),
                    'userName' => $channelResponse->items[0]->snippet->title ?? '',
                    'userId' => $channelResponse->items[0]->id ?? '',
                ]
            ];
        } catch (\Exception $e) {
            return ['status' => false, 'data' => $e->getMessage()];
        }
    }

    public function postImage($message, $imagePaths, $accessToken)
    {
        return [
            'status' => false,
            'data' => 'YouTube API does not support image-only posts'
        ];
    }


    public function postVideo($message, $videoPath, $accessToken)
    {
        Log::info('YouTube 开始发布视频帖子');
        /*
        $ossPath = ltrim(parse_url($videoPath, PHP_URL_PATH), '/');
        $fileSize = $this->getOssFileSize($ossPath);
        if ($fileSize['status'] === false) {
            return ['status' => false, 'data' => $fileSize['data']];
        }*/

        $backup_field1 = $this->configData['postData']['backup_field1'] ?? '';
        $backup_field1 = json_decode($backup_field1, true);
        $title = $backup_field1['yutube_title'] ?? '';
        $category = $backup_field1['yutube_category'] ?? '';

        $videoPath = toStoragePath($videoPath);
        // 处理 OAuth 回调
        $this->client->setAccessToken($accessToken);
        // 初始化 YouTube 服务
        $youtube = new Google_Service_YouTube($this->client);
        try {
            // 定义视频元数据
            $snippetData = [
                'title' => $title,
                'description' => $message,
                'tags' => [],
                'categoryId' => $category // 人物与博客
            ];
            Log::info('YouTube 定义视频元数据'.json_encode($snippetData));
            $snippet = new Google_Service_YouTube_VideoSnippet();
            $snippet->setTitle($snippetData['title']);
            $snippet->setDescription($snippetData['description']);
            $snippet->setTags($snippetData['tags']);//'test', 'api'
            $snippet->setCategoryId($snippetData['categoryId']); // 人物与博客
            // 设置视频状态
            $status = new Google_Service_YouTube_VideoStatus();
            $status->setPrivacyStatus('public'); // public, private, unlisted
            $status->setMadeForKids(true);// 是否为儿童视频
            // 创建视频对象
            $video = new Google_Service_YouTube_Video();
            $video->setSnippet($snippet);
            $video->setStatus($status);
            // 上传视频
            $this->client->setDefer(true);
            $insertRequest = $youtube->videos->insert('snippet,status', $video);
            Log::info('YouTube 分块上传视频');
            $media = new Google_Http_MediaFileUpload(
                $this->client,
                $insertRequest,
                'video/*',
                null,
                true,
                2 * 1048576 // 分块大小 2MB
            );
            $media->setFileSize(filesize($videoPath)); // 替换为视频文件路径
            $status = false;
            $handle = fopen($videoPath, 'rb');
            while (!$status && !feof($handle)) {
                $chunk = fread($handle, 2 * 1048576);
                $status = $media->nextChunk($chunk);
            }
            fclose($handle);
            $this->client->setDefer(false);
            //echo "Video uploaded: " . $status['id'];
            Log::info('视频上传成功:  '.$status['id']);
            return ['status' => true,
                'data' => [
                    'responseIds' => [$status['id']],
                ]];
        } catch (Google_Service_Exception $e) {
            return ['status' => false, 'data' => $e->getMessage()];
        } catch (Google_Exception $e) {
            return ['status' => false, 'data' => $e->getMessage()];
        }
    }



    public function getVideoCategories($regionCode = 'US')
    {
        try {
            $youtube = new Google_Service_YouTube($this->client);
            $response = $youtube->videoCategories->listVideoCategories('snippet', [
                'regionCode' => $regionCode
            ]);
            $categories = [];
            foreach ($response->items as $category) {
                if ($category->snippet->assignable) {
                    $categories[$category->id] = $category->snippet->title;
                }
            }
            return [
                'status' => true,
                'data' => $categories
            ];
        } catch (\Google_Service_Exception $e) {
            $error = json_decode($e->getMessage(), true)['error']['message'] ?? $e->getMessage();
            return ['status' => false, 'data' => $error];
        }
    }



    public function getComments($postId)
    {
        try {
            $youtube = new Google_Service_YouTube($this->client);
            $response = $youtube->commentThreads->listCommentThreads('snippet', [
                'videoId' => $postId,
                'maxResults' => 100
            ]);

            $comments = [];
            foreach ($response->items as $item) {
                $comment = $item->snippet->topLevelComment->snippet;
                $comments[] = [
                    'id' => $item->id,
                    'text' => $comment->textDisplay,
                    'author' => $comment->authorDisplayName,
                    'createdAt' => $comment->publishedAt
                ];
            }

            return ['status' => true, 'data' => $comments];
        } catch (\Exception $e) {
            Log::error('YouTube get comments error: '.$e->getMessage());
            return ['status' => false, 'error' => $e->getMessage()];
        }
    }

    public function replyToComment($commentId)
    {
        $text = '';
        try {
            $youtube = new Google_Service_YouTube($this->client);

            $commentSnippet = new \Google_Service_YouTube_CommentSnippet();
            $commentSnippet->setTextOriginal($text);
            $commentSnippet->setParentId($commentId);

            $comment = new \Google_Service_YouTube_Comment();
            $comment->setSnippet($commentSnippet);

            $response = $youtube->comments->insert('snippet', $comment);

            return [
                'status' => true,
                'data' => [
                    'commentId' => $response->getId(),
                    'text' => $text
                ]
            ];
        } catch (\Exception $e) {
            Log::error('YouTube reply error: '.$e->getMessage());
            return ['status' => false, 'error' => $e->getMessage()];
        }
    }

    public function deleteComment($commentId)
    {
        try {
            $youtube = new Google_Service_YouTube($this->client);
            $youtube->comments->delete($commentId);
            return ['status' => true];
        } catch (\Exception $e) {
            Log::error('YouTube delete comment error: '.$e->getMessage());
            return ['status' => false, 'error' => $e->getMessage()];
        }
    }

    public function refreshToken($refreshToken)
    {
        try {
            $this->client->refreshToken($refreshToken);
            return $this->client->getAccessToken();
        } catch (\Exception $e) {
            Log::error('YouTube refresh token error: '.$e->getMessage());
            return ['error' => $e->getMessage()];
        }
    }

    public function refreshAccessToken($refreshToken)
    {
        try {
            $newToken = $this->client->fetchAccessTokenWithRefreshToken($refreshToken);
            return [
                'status' => true,
                'data' => [
                    'access_token' => $newToken['access_token'],
                    'expires_at' => Carbon::now()->addSeconds($newToken['expires_in']),
                    'refresh_token' => $newToken['refresh_token'],
                ]
            ];
        } catch (\Exception $e) {
            return ['status' => false, 'error' => 'Failed to refresh access token: '.$e->getMessage()];
        }
    }

    /*
     * 返回oss文件大小 （字节）
     * $pathName : 'path/to/your/file.txt'
     */
    /*
    public function getOssFileSize($pathName)
    {
        // 配置信息
        $accessKeyId = env('OSS_ACCESS_KEY_ID');
        $accessKeySecret = env('OSS_ACCESS_KEY_SECRET');
        $endpoint = env('OSS_ENDPOINT'); // 替换为你的 Region Endpoint
        $bucketName = env('OSS_BUCKET');
        $objectName = $pathName; // OSS 文件路径
        try {
            // 创建 OssClient 实例
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
            // 获取文件元数据
            $metadata = $ossClient->headObject($bucketName, $objectName);
            // 从元数据中获取文件大小（字节）
            $fileSize = $metadata['content-length'];
            return ['status' => true, 'data' => $fileSize];
        } catch (OssException $e) {
            // 错误处理
            return ['status' => false, 'data' => $e->getMessage()];
        }
    }
    */
}
