<?php

namespace BitApps\SocialPro\HTTP\Services\Social\ThreadsService;

use BitApps\Social\Deps\BitApps\WPKit\Http\Client\HttpClient;
use BitApps\Social\HTTP\Services\Interfaces\AuthServiceInterface;
use BitApps\Social\HTTP\Services\Traits\LoggerTrait;
use BitApps\Social\Model\Account;
use BitApps\Social\Utils\Common;
use BitApps\Social\Utils\Hash;

class ThreadsOAuth2Service implements AuthServiceInterface
{
    use Common, LoggerTrait;

    private $httpHandler;

    private $baseUrl = 'https://graph.threads.net';

    private $accessTokenUrl = 'https://graph.threads.net/oauth/access_token?';

    private $longLiveAccessTokenUrl = 'https://graph.threads.net/access_token?';

    private $profileUrl = 'https://graph.threads.net/v1.0/me?';

    private $accessToken;

    private $userId;

    private $userAccountInfoUrl;

    private $getAccountsUrl;

    private $getAllGroupUrl;

    private $expiresIn;

    public function __construct()
    {
        $this->httpHandler = new HttpClient();
    }

    // TODO: encode only query params value. should  refactor
    public function urlParamEncode($url)
    {
        // Parse the URL to get the query string
        $queryString = parse_url($url, PHP_URL_QUERY);

        // Separate the query string into key-value pairs
        parse_str($queryString, $params);

        if (isset($params['rest_route'])) {
            // Encode each value in the parameters array
            foreach ($params as $key => $value) {
                $params[$key] = urlencode($value);
            }

            // Rebuild the query string

            $newQueryString = 'rest_route=' . $params['rest_route'];

            // Reconstruct the URL with the encoded query string
            return str_replace($queryString, $newQueryString, $url);
        }

        return $url;
    }

    public function authHandler($request)
    {
        $body = $request->body();

        $appId = $body['payload']['appId'];
        $appKey = $body['payload']['appSecret'];
        $redirectUri = $body['payload']['redirectUri'];
        $code = $body['payload']['code'];

        $shortAccessTokenParams = [
            'client_id'     => $appId,
            'client_secret' => $appKey,
            'redirect_uri'  => $this->urlParamEncode($redirectUri),
            'code'          => $code,
        ];

        $shortAccessTokenUrlWithParams = $this->accessTokenUrl . http_build_query($shortAccessTokenParams);

        $shortAccessTokenResponse = $this->httpHandler->request($shortAccessTokenUrlWithParams, 'GET', []);

        if (isset($shortAccessTokenResponse->error_type)) {
            return (object) ['status' => 'error', 'message' => $shortAccessTokenResponse->error->message];
        }

        $this->userId = $shortAccessTokenResponse->user_id;

        $longLiveAccessTokenParams = [
            'grant_type'    => 'th_exchange_token',
            'client_secret' => $appKey,
            'access_token'  => $shortAccessTokenResponse->access_token,
        ];

        $longLiveAccessTokenUrlWithParams = $this->longLiveAccessTokenUrl . http_build_query($longLiveAccessTokenParams);

        $longLiveAccessTokenData = $this->httpHandler->request($longLiveAccessTokenUrlWithParams, 'GET', []);

        if (isset($longLiveAccessTokenData->error)) {
            return (object) ['status' => 'error', 'message' => $longLiveAccessTokenData->error->message];
        }

        $this->accessToken = $longLiveAccessTokenData->access_token;

        $this->expiresIn = $longLiveAccessTokenData->expires_in;

        $profileInfo = $this->getProfileInfo();

        return $this->organizeThreadsProfile($profileInfo);
    }

    public function getProfileInfo()
    {
        $params = [
            'fields'       => 'name,username,threads_profile_picture_url,is_verified',
            'access_token' => $this->accessToken
        ];

        $profileUrlWithParams = $this->profileUrl . http_build_query($params);

        return $this->httpHandler->request($profileUrlWithParams, 'GET', []);
    }

    public function organizeThreadsProfile($profile)
    {
        $accountId = $this->userId;
        $accountName = $profile->name ?? $profile->username;

        $accountDetails = [
            'profile_id'   => $accountId,
            'account_id'   => $accountId,
            'account_name' => $accountName,
            'account_type' => 'profile',
            'verified'     => $profile->is_verified,
            'user_name'    => $profile->username,
            'platform'     => 'threads',
            'icon'         => $profile->threads_profile_picture_url ?? null,
            'access_token' => Hash::encrypt($this->accessToken),
            'expiresIn'    => time() + (int) $this->expiresIn,
        ];

        $userData = [
            'profile_id'   => $accountId,
            'account_id'   => $accountId,
            'account_name' => $accountName,
            'details'      => json_encode($accountDetails),
            'platform'     => 'threads',
            'account_type' => Account::accountType['DEFAULT'],
            'status'       => Account::ACCOUNT_STATUS['active'],
        ];

        $isConnected = Account::where('account_id', $accountId)->count();

        return [
            [
                'account'     => $userData,
                'isConnected' => (bool) $isConnected,
            ]
        ];
    }
}
