<?php

namespace BitApps\PiPro\src\Integrations\Gmail;

// Prevent direct script access
if (!\defined('ABSPATH')) {
    exit;
}


use BitApps\PiPro\Deps\BitApps\WPKit\Helpers\JSON;

final class GmailService
{
    private const BASE_URL = 'https://gmail.googleapis.com/gmail/v1/users/me';

    private $http;

    private $headers;

    public function __construct($httpClient, $headers)
    {
        $this->http = $httpClient;
        $this->headers = $headers;
    }

    public function prepareRawMessage($inputData, $toEmails, $ccEmails, $bccEmails, $attachments)
    {
        $boundary = uniqid(mt_rand(), true);

        $raw = "From: {$inputData['from_name']} <{$inputData['from_email']}>\r\n";
        $raw .= 'To: ' . implode(', ', array_column($toEmails, 'email')) . "\r\n";
        if (!empty($ccEmails)) {
            $raw .= 'Cc: ' . implode(', ', array_column($ccEmails, 'email')) . "\r\n";
        }
        if (!empty($bccEmails)) {
            $raw .= 'Bcc: ' . implode(', ', array_column($bccEmails, 'email')) . "\r\n";
        }
        if (!empty($inputData['reply_to'])) {
            $raw .= "Reply-To: {$inputData['reply_to']}\r\n";
        }
        $raw .= "Subject: {$inputData['subject']}\r\n";
        $raw .= "MIME-Version: 1.0\r\n";
        $raw .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n\r\n";

        // Body part
        $raw .= "--{$boundary}\r\n";
        $raw .= "Content-Type: text/{$inputData['body_type']}; charset=UTF-8\r\n";
        $raw .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
        $raw .= $inputData['body'] . "\r\n\r\n";

        // Attachments
        if (!empty($attachments)) {
            $allowedMimeTypes = wp_get_mime_types();
            $finfo = null;

            if (\function_exists('finfo_open')) {
                $finfo = finfo_open(FILEINFO_MIME_TYPE);
            }

            foreach ($attachments as $file) {
                $fileContent = file_get_contents($file['url']);
                if ($fileContent === false) {
                    continue;
                }


                $fileData = chunk_split(base64_encode($fileContent));
                $mimeType = '';

                if ($finfo) {
                    $mimeType = finfo_buffer($finfo, $fileContent);
                }

                if (empty($mimeType) || !\in_array($mimeType, $allowedMimeTypes)) {
                    $mimeType = 'application/octet-stream';
                }

                $raw .= "--{$boundary}\r\n";
                $raw .= "Content-Type: {$mimeType}; name=\"{$file['name']}\"\r\n";
                $raw .= "Content-Disposition: inline; filename=\"{$file['name']}\"\r\n";
                $raw .= "Content-Transfer-Encoding: base64\r\n\r\n";
                $raw .= $fileData . "\r\n\r\n";
            }

            if ($finfo) {
                finfo_close($finfo);
            }
        }

        $raw .= "--{$boundary}--";

        return rtrim(strtr(base64_encode($raw), '+/', '-_'), '=');
    }

    public function sendEmail($inputData, $toEmails, $ccEmails, $bccEmails, $attachments)
    {
        $rawMessage = $this->prepareRawMessage($inputData, $toEmails, $ccEmails, $bccEmails, $attachments);

        // Prepare payload
        $payload = JSON::encode(
            [
                'raw' => $rawMessage
            ]
        );

        $response = $this->http->request(self::BASE_URL . '/messages/send', 'POST', $payload);

        return [
            'response'    => $response,
            'payload'     => $payload,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function createDraftEmail($inputData, $toEmails, $ccEmails, $bccEmails, $attachments)
    {
        $rawMessage = $this->prepareRawMessage($inputData, $toEmails, $ccEmails, $bccEmails, $attachments);

        $payload = JSON::encode(
            [
                'message' => ['raw' => $rawMessage]
            ]
        );

        $response = $this->http->request(self::BASE_URL . '/drafts', 'POST', $payload);

        return [
            'response'    => $response,
            'payload'     => $payload,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function findEmail($inputData)
    {
        $response = $this->http->request(self::BASE_URL . '/messages?q=' . urlencode($inputData['query']), 'GET', null, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function deleteEmail($inputData)
    {
        $messageId = $inputData['message_id'];
        if ($inputData['is_permanently_delete'] === 'yes') {
            // PERMANENT DELETE
            $url = self::BASE_URL . "/messages/{$messageId}";
            $method = 'DELETE';
        } else {
            // MOVE TO TRASH
            $url = self::BASE_URL . "/messages/{$messageId}/trash";
            $method = 'POST';
        }
        $response = $this->http->request($url, $method, [], $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function getEmailDetails($inputData)
    {
        $url = add_query_arg('format', 'full', self::BASE_URL . "/messages/{$inputData['message_id']}");
        $response = $this->http->request($url, 'GET', null, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function getLabels($inputData)
    {
        $url = self::BASE_URL . '/labels';

        $response = $this->http->request($url, 'GET', null, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function addLabelToEmail($inputData)
    {
        $url = self::BASE_URL . "/messages/{$inputData['message_id']}/modify";

        $payload = JSON::encode(
            [
                'addLabelIds' => [$inputData['label_id']]
            ]
        );

        $response = $this->http->request($url, 'POST', $payload, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function removeLabelToEmail($inputData)
    {
        $url = self::BASE_URL . "/messages/{$inputData['message_id']}/modify";

        $payload = JSON::encode(
            [
                'removeLabelIds' => [$inputData['label_id']]
            ]
        );

        $response = $this->http->request($url, 'POST', $payload, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function sendDraft($inputData)
    {
        $url = self::BASE_URL . '/drafts/send';

        $payload = JSON::encode(
            [
                'id' => $inputData['draft_id']
            ]
        );
        $response = $this->http->request($url, 'POST', $payload, $this->headers);

        return [
            'response'    => $response,
            'payload'     => $inputData,
            'status_code' => $this->http->getResponseCode()
        ];
    }

    public function replyToEmail($inputData, $toEmails, $ccEmails, $bccEmails, $attachments)
    {
        $rawMessage = $this->prepareRawMessage($inputData, $toEmails, $ccEmails, $bccEmails, $attachments);

        $payload = JSON::encode(
            [
                'raw'      => $rawMessage,
                'threadId' => $inputData['thread_id']
            ]
        );

        $response = $this->http->request(self::BASE_URL . '/messages/send', 'POST', $payload);

        return [
            'response'    => $response,
            'payload'     => $payload,
            'status_code' => $this->http->getResponseCode()
        ];
    }
}
