<?php

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

use AllowDynamicProperties;
use BitApps\Social\Config;
use BitApps\Social\Deps\BitApps\WPKit\Hooks\Hooks;
use BitApps\Social\HTTP\Services\Interfaces\SocialInterface;
use BitApps\Social\HTTP\Services\Traits\LoggerTrait;
use BitApps\Social\Model\Schedule;
use BitApps\Social\Utils\Common;
use BitApps\Social\Utils\Hash;
use BitApps\SocialPro\Deps\BitApps\WPKit\Http\Client\HttpClient;

#[AllowDynamicProperties]
class PostPublishPinterestService implements SocialInterface
{
    use Common, LoggerTrait;

    public const VERSION = 'v5/';

    private $httpHandler;

    /**
     * @var RefreshService $refreshHandler
     */
    private $refreshHandler;

    private $baseUrl = 'https://api.pinterest.com/';

    private $postUrl = 'https://www.pinterest.com/pin/';

    private $pinterestData = [];

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

    public function publishPost($data)
    {
        $post = $data['post'] ?? null;
        $post_data = [];
        $template = (object) $data['template'];
        $scheduleType = $data['schedule_type'] ?? null;
        $account_detail = $data['account_details'];
        $schedule_id = $data['schedule_id'] ?? null;
        $account_id = $account_detail->account_id;
        $account_name = $account_detail->account_name;

        $access_token = Hash::decrypt($account_detail->access_token);
        $expires_in = $account_detail->expires_in;
        $refresh_token = Hash::decrypt($account_detail->refresh_token);
        $refresh_token_expires_in = $account_detail->refresh_token_expires_in;

        $client_id = Hash::decrypt($account_detail->client_id);
        $client_secret = Hash::decrypt($account_detail->client_secret);

        $tokenUpdateData = $this->refreshHandler->tokenExpiryCheck($client_id, $client_secret, $access_token, $expires_in, $refresh_token, $refresh_token_expires_in);

        if ($tokenUpdateData->access_token !== $access_token) {
            $account_detail->access_token = Hash::encrypt($tokenUpdateData->access_token);
            $account_detail->expires_in = $tokenUpdateData->expires_in;
            $account_detail->refresh_token = Hash::encrypt($tokenUpdateData->refresh_token);
            $account_detail->refresh_token_expires_in = $tokenUpdateData->refresh_token_expires_in;
            $this->refreshHandler->saveRefreshedToken($account_detail);
        }

        if ($scheduleType === Schedule::scheduleType['DIRECT_SHARE']) {
            $templateMedia = array_map(function ($item) {
                return $item['url'];
            }, $template->media);

            $post_data['content'] = $template->content ?? null;
            $post_data['title'] = $template->title ?? null;
            $post_data['media'] = $templateMedia ?? null;
            $post_data['link'] = $template->link ?? null;

            $template->isFeaturedImage = false;
            $template->isLinkCard = false;

            if (!empty($templateMedia)) {
                $template->isFeaturedImage = true;
            }
            if (empty($templateMedia) && !empty($template->link)) {
                $template->isLinkCard = true;
            }
        } else {
            $template->platform = 'pinterest';
            $post_data = $this->replacePostContent($post['ID'], $template);

            $post_data['title'] = $this->replaceTagValue($template->title, (object) $post);
        }

        $this->pinterestData['post'] = $this->normalizePostData($post_data, true);

        $postPublishResponse = $this->pinterestPostPublish($post_data, $account_detail, $access_token);

        if (\is_object($postPublishResponse)) {
            $pinUrl = $postPublishResponse->id ? $this->postUrl . $postPublishResponse->id : null;
        }

        $responseData = [
            'schedule_id' => $schedule_id,
            'details'     => [
                'account_id'   => $account_id,
                'account_name' => $account_name,
                'post_id'      => $post['ID'] ?? null,
                'response'     => $postPublishResponse,
                'post_url'     => $pinUrl
            ],
            'platform' => 'pinterest',
            'status'   => \is_object($postPublishResponse) && property_exists($postPublishResponse, 'id') ? 1 : 0
        ];

        $hookResponse = [
            'account_id'   => $account_id,
            'account_name' => $account_name,
            'post_url'     => $responseData['details']['post_url'],
            'status'       => $responseData['status'],
        ];

        $this->pinterestData['platform'] = 'pinterest';
        $this->pinterestData['response'] = $hookResponse;

        Hooks::doAction(Config::withPrefix('pinterest_post_publish'), $this->normalizePostData($post_data), $hookResponse);

        if (!(\array_key_exists('keepLogs', $data) && $data['keepLogs'] === false)) {
            $this->logCreate($responseData);
        }

        return $this->pinterestData;
    }

    public function pinterestPostPublish($post_data, $account_detail, $access_token)
    {
        $titleMaxLength = 100;

        $post_title = !empty($post_data['title']) ? substr($post_data['title'], 0, $titleMaxLength) : '';

        $post_content = $post_data['content'] ?? null;
        $media = $post_data['media'] ?? [];
        $post_link = $post_data['link'] ?? null;

        return $this->pinCreate($account_detail, $access_token, $post_title, $post_content, $post_link, $media);
    }

    public function pinCreate($account_detail, $access_token, $post_title, $post_content, $post_link, $media)
    {
        $pinImages = $media;
        $board_id = $account_detail->account_id;

        if (empty($pinImages)) {
            return [
                'status'    => 'error',
                'error_msg' => 'Must have image for create pin in Pinterest.'
            ];
        }

        if (mb_strlen($post_content) > 500) {
            $post_content = Helper::cutText($post_content, 497);
        }

        if (\count($pinImages) > 1) {
            foreach ($pinImages as $pinImage) {
                $result[] = $this->uploadBase64Image($pinImage, $board_id, $post_title, $post_content, $post_link, $access_token);
            }

            return end($result);
        }

        $pinImage = $pinImages[0];

        return $this->uploadBase64Image($pinImage, $board_id, $post_title, $post_content, $post_link, $access_token);
    }

    public function uploadBase64Image($pinImage, $board_id, $post_title, $post_content, $post_link, $access_token)
    {
        $mediaInfo = $this->fileInfoAndBase64($pinImage);

        $sendData = [
            'board_id' => $board_id,

            'description' => $post_content,
            'alt_text'    => $post_title
        ];

        if (!empty($post_title)) {
            $sendData['title'] = $post_title;
        }

        if (!empty($post_link)) {
            $sendData['link'] = $post_link;
        }

        $sendData['media_source']['source_type'] = 'image_base64';
        $sendData['media_source']['content_type'] = $mediaInfo['type'];
        $sendData['media_source']['data'] = $mediaInfo['base64'];

        $pinCreateUrl = $this->baseUrl . static::VERSION . 'pins';

        $header = [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Bearer ' . $access_token
        ];

        return $this->httpHandler->request($pinCreateUrl, 'POST', wp_json_encode($sendData), $header, null);
    }

    private function fileInfoAndBase64($filePath)
    {
        $fileContent = @file_get_contents($filePath);

        if ($fileContent === false) {
            $response = wp_remote_get($filePath, [
                'timeout'    => 30,
                'user-agent' => 'Mozilla/5.0 (compatible; WordPress/' . get_bloginfo('version') . '; +' . get_bloginfo('url') . ')',
                'sslverify'  => false,
            ]);

            if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
                return ['name' => 'image.jpg', 'type' => 'image/jpeg', 'base64' => ''];
            }

            $fileContent = wp_remote_retrieve_body($response);
        }

        $attachmentId = attachment_url_to_postid($filePath);
        $fileInfo = pathinfo($filePath);

        if ($attachmentId) {
            // Use wp_check_filetype_and_ext for WordPress media
            $wpCheck = wp_check_filetype_and_ext($filePath, $fileInfo['basename']);
            $mimeType = $wpCheck['type'] ?? null;
        } else {
            // For non-WordPress media, use Helper for MIME type detection
            $mimeType = Helper::mimeContentType($filePath);
        }

        $fileName = $fileInfo['basename'] ?? 'image.jpg';

        $fileType = $mimeType === 'image/webp' ? 'image/png' : $mimeType;
        $base64 = base64_encode($fileContent);

        return [
            'name'   => $fileName,
            'type'   => $fileType,
            'base64' => $base64
        ];
    }
}
