<?php
if (!defined('ABSPATH')) {
    exit;
}

class VMO_Promotion_YouTube_Connector extends VMO_Promotion_OAuth2_Connector {
    protected function build_authorization_url(array $settings, array $scopes, $state) {
        return add_query_arg(array(
            'client_id' => $this->get_client_identifier($settings),
            'redirect_uri' => $this->get_callback_url(),
            'response_type' => 'code',
            'scope' => implode(' ', $scopes),
            'state' => $state,
            'access_type' => 'offline',
            'include_granted_scopes' => 'true',
            'prompt' => 'consent',
        ), 'https://accounts.google.com/o/oauth2/v2/auth');
    }

    protected function get_token_endpoint() {
        return 'https://oauth2.googleapis.com/token';
    }

    protected function discover_remote_accounts($user_id, array $token_context, array $request_context = array()) {
        $access_token = (string) ($token_context['access_token'] ?? '');
        if ($access_token === '') {
            return array();
        }

        $response = $this->api_get('https://www.googleapis.com/youtube/v3/channels', $access_token, array(
            'part' => 'snippet,contentDetails,status',
            'mine' => 'true',
            'maxResults' => 50,
        ));

        if (is_wp_error($response)) {
            return $response;
        }

        $accounts = array();
        foreach ((array) ($response['items'] ?? array()) as $channel) {
            $channel_id = sanitize_text_field($channel['id'] ?? '');
            if ($channel_id === '') {
                continue;
            }

            $accounts[] = array(
                'platform_key' => 'youtube',
                'platform_label' => 'YouTube',
                'external_account_id' => $channel_id,
                'display_name' => sanitize_text_field($channel['snippet']['title'] ?? ('YouTube Channel ' . $channel_id)),
                'auth_status' => 'connected',
                'connection_metadata' => array(
                    'connection_role' => 'youtube_channel',
                    'channel_id' => $channel_id,
                    'uploads_playlist_id' => sanitize_text_field($channel['contentDetails']['relatedPlaylists']['uploads'] ?? ''),
                    'long_uploads_status' => sanitize_key($channel['status']['longUploadsStatus'] ?? ''),
                ),
            );
        }

        return $accounts;
    }

    public function publish_text_post(array $input) {
        return new WP_Error('provider_not_ready', 'YouTube publishing requires a video asset. Use the media publishing flow for this provider.');
    }

    public function publish_media_post(array $input) {
        $account = $this->get_platform_account_record($input);
        if (empty($account['access_token'])) {
            return new WP_Error('missing_connected_account', 'A connected YouTube channel is required before publishing.');
        }

        $content_item = (array) ($input['content_item'] ?? array());
        $asset = $this->extract_primary_asset($content_item);
        if (empty($asset['url'])) {
            return new WP_Error('missing_media_asset', 'YouTube publishing requires a video asset.');
        }

        $mime = strtolower((string) ($asset['type'] ?? ''));
        if (strpos($mime, 'video/') !== 0) {
            return new WP_Error('invalid_media_type', 'YouTube publishing requires a video file.');
        }

        $asset_response = wp_remote_get($asset['url'], array(
            'timeout' => 180,
        ));
        if (is_wp_error($asset_response)) {
            return $asset_response;
        }

        $binary = wp_remote_retrieve_body($asset_response);
        if ($binary === '') {
            return new WP_Error('empty_asset', 'YouTube upload could not read the selected video asset.');
        }

        $metadata = array(
            'snippet' => array(
                'title' => sanitize_text_field($content_item['title'] ?? $asset['name'] ?? 'VMO Video Post'),
                'description' => $this->get_post_caption($content_item),
                'categoryId' => '22',
            ),
            'status' => array(
                'privacyStatus' => 'public',
                'selfDeclaredMadeForKids' => false,
            ),
        );

        $init = wp_remote_post('https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status', array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => 'Bearer ' . $account['access_token'],
                'Accept' => 'application/json',
                'Content-Type' => 'application/json; charset=UTF-8',
                'X-Upload-Content-Length' => (string) strlen($binary),
                'X-Upload-Content-Type' => $mime,
            ),
            'body' => wp_json_encode($metadata),
        ));

        if (is_wp_error($init)) {
            return $init;
        }

        $status = (int) wp_remote_retrieve_response_code($init);
        if ($status >= 400) {
            return new WP_Error('provider_api_error', 'YouTube upload session could not be created.', array(
                'status' => $status,
                'response' => wp_remote_retrieve_body($init),
            ));
        }

        $headers = wp_remote_retrieve_headers($init);
        $upload_url = '';
        if (is_object($headers) && method_exists($headers, 'offsetGet')) {
            $upload_url = (string) $headers->offsetGet('location');
        } elseif (is_array($headers) && !empty($headers['location'])) {
            $upload_url = (string) $headers['location'];
        }

        if ($upload_url === '') {
            return new WP_Error('provider_api_error', 'YouTube resumable upload URL was not returned.');
        }

        $upload = wp_remote_request($upload_url, array(
            'method' => 'PUT',
            'timeout' => 600,
            'headers' => array(
                'Authorization' => 'Bearer ' . $account['access_token'],
                'Content-Type' => $mime,
                'Content-Length' => (string) strlen($binary),
            ),
            'body' => $binary,
        ));

        if (is_wp_error($upload)) {
            return $upload;
        }

        $upload_status = (int) wp_remote_retrieve_response_code($upload);
        $upload_body = json_decode((string) wp_remote_retrieve_body($upload), true);
        if (!is_array($upload_body)) {
            $upload_body = array();
        }

        if ($upload_status >= 400) {
            return new WP_Error('provider_api_error', 'YouTube video upload failed.', array(
                'status' => $upload_status,
                'response' => $upload_body,
            ));
        }

        return array(
            'provider_post_id' => sanitize_text_field($upload_body['id'] ?? ''),
            'message' => 'Published video to YouTube.',
            'response' => $upload_body,
        );
    }

    public function list_replies(array $input) {
        $account = $this->get_platform_account_record($input);
        if (empty($account['access_token'])) {
            return new WP_Error('missing_connected_account', 'A connected YouTube channel is required before loading comments.');
        }

        $video_id = $this->get_video_id($input);
        if ($video_id === '') {
            return new WP_Error('missing_provider_post', 'A YouTube video ID is required before loading comments.');
        }

        $response = $this->api_get('https://www.googleapis.com/youtube/v3/commentThreads', $account['access_token'], array(
            'part' => 'snippet,replies',
            'videoId' => $video_id,
            'maxResults' => 100,
            'textFormat' => 'plainText',
            'order' => 'time',
        ));
        if (is_wp_error($response)) {
            return $response;
        }

        return array(
            'platform_key' => 'youtube',
            'video_id' => $video_id,
            'replies' => array_values((array) ($response['items'] ?? array())),
            'response' => $response,
        );
    }

    public function reply_to_comment(array $input) {
        $account = $this->get_platform_account_record($input);
        if (empty($account['access_token'])) {
            return new WP_Error('missing_connected_account', 'A connected YouTube channel is required before replying.');
        }

        $parent_id = sanitize_text_field($input['comment_id'] ?? $input['provider_comment_id'] ?? $input['in_reply_to_id'] ?? '');
        if ($parent_id === '') {
            return new WP_Error('missing_comment_id', 'YouTube reply publishing requires a parent comment ID.');
        }

        $text = sanitize_textarea_field($input['message'] ?? $input['text'] ?? '');
        if ($text === '' && !empty($input['content_item'])) {
            $text = $this->get_post_caption((array) $input['content_item']);
        }

        if ($text === '') {
            return new WP_Error('missing_reply_text', 'YouTube reply publishing requires reply text.');
        }

        $response = $this->api_post('https://www.googleapis.com/youtube/v3/comments?part=snippet', $account['access_token'], array(
            'snippet' => array(
                'parentId' => $parent_id,
                'textOriginal' => $text,
            ),
        ));
        if (is_wp_error($response)) {
            return $response;
        }

        return array(
            'platform_key' => 'youtube',
            'provider_reply_id' => sanitize_text_field($response['id'] ?? ''),
            'message' => 'Reply published to YouTube.',
            'response' => $response,
        );
    }

    public function fetch_metrics(array $input) {
        $account = $this->get_platform_account_record($input);
        if (empty($account['access_token'])) {
            return new WP_Error('missing_connected_account', 'A connected YouTube channel is required before loading metrics.');
        }

        $video_id = $this->get_video_id($input);
        if ($video_id === '') {
            return new WP_Error('missing_post_id', 'YouTube metrics lookup requires a video ID.');
        }

        $response = $this->api_get('https://www.googleapis.com/youtube/v3/videos', $account['access_token'], array(
            'part' => 'statistics,snippet',
            'id' => $video_id,
        ));
        if (is_wp_error($response)) {
            return $response;
        }

        $video = (array) ((array) ($response['items'] ?? array())[0] ?? array());
        if (empty($video)) {
            return new WP_Error('provider_api_error', 'YouTube metrics lookup did not return the requested video.', $response);
        }

        $statistics = (array) ($video['statistics'] ?? array());
        $views = max(0, (int) ($statistics['viewCount'] ?? 0));
        $likes = max(0, (int) ($statistics['likeCount'] ?? 0));
        $comments = max(0, (int) ($statistics['commentCount'] ?? 0));
        $favorites = max(0, (int) ($statistics['favoriteCount'] ?? 0));
        $engagements = $likes + $comments + $favorites;
        $engagement_rate = $views > 0 ? round(($engagements / $views) * 100, 4) : 0;

        return array(
            'platform_key' => 'youtube',
            'provider_post_id' => $video_id,
            'snapshot_time' => current_time('mysql'),
            'metrics' => array(
                'impressions' => $views,
                'reach' => $views,
                'clicks' => 0,
                'comments' => $comments,
                'shares' => 0,
                'saves' => $favorites,
                'likes' => $likes,
                'views' => $views,
                'ctr' => 0,
                'engagement_rate' => $engagement_rate,
            ),
            'response' => $response,
        );
    }

    protected function get_video_id(array $input) {
        $video_id = sanitize_text_field($input['provider_post_id'] ?? $input['post_id'] ?? $input['video_id'] ?? '');
        if ($video_id === '' && !empty($input['job']['provider_post_id'])) {
            $video_id = sanitize_text_field($input['job']['provider_post_id']);
        }
        if ($video_id === '' && !empty($input['distribution_job']['provider_post_id'])) {
            $video_id = sanitize_text_field($input['distribution_job']['provider_post_id']);
        }

        return $video_id;
    }
}
