<?php

namespace FleekDash\Services;

use Google_Client;
use Google_Service_Gmail;
use Google_Service_Gmail_Message;
use Exception;

class Gmail
{
    private $client;
    private $service;
    private $user_id;

    public function __construct($user_id = null)
    {
        $this->user_id = $user_id ?? \get_current_user_id();
        $this->init_client();
    }

    private function init_client()
    {
        $this->client = new Google_Client();
        $this->client->setClientId(\get_option('fleekdash_gmail_client_id'));
        $this->client->setClientSecret(\get_option('fleekdash_gmail_client_secret'));
        $this->client->setRedirectUri(\site_url('/wp-json/fleekdash/v1/gmail/callback'));
        $this->client->addScope(Google_Service_Gmail::GMAIL_READONLY);

        $token = \get_user_meta($this->user_id, 'fleekdash_gmail_token', true);

        if (!empty($token)) {
            $this->client->setAccessToken($token);

            if ($this->client->isAccessTokenExpired()) {
                if ($this->client->getRefreshToken()) {
                    try {
                        $this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken());
                        \update_user_meta($this->user_id, 'fleekdash_gmail_token', $this->client->getAccessToken());
                    } catch (Exception $e) {
                        // Token refresh failed, user needs to reconnect
                        \delete_user_meta($this->user_id, 'fleekdash_gmail_token');
                        throw new Exception('Gmail authentication expired. Please reconnect your account.');
                    }
                } else {
                    // No refresh token, user needs to reconnect
                    \delete_user_meta($this->user_id, 'fleekdash_gmail_token');
                    throw new Exception('Gmail authentication expired. Please reconnect your account.');
                }
            }

            $this->service = new Google_Service_Gmail($this->client);
        } else {
            throw new Exception('Gmail not connected. Please connect your account first.');
        }
    }

    /**
     * Get user's Gmail profile information
     */
    public function get_profile()
    {
        try {
            return $this->service->users->getProfile('me');
        } catch (Exception $e) {
            throw new Exception('Failed to get Gmail profile: ' . $e->getMessage());
        }
    }

    /**
     * List emails from Gmail inbox
     */
    public function list_messages($max_results = 10, $query = '')
    {
        try {
            $opt_param = [
                'maxResults' => $max_results,
                'labelIds' => ['INBOX'],
            ];

            if (!empty($query)) {
                $opt_param['q'] = $query;
            }

            $messages_response = $this->service->users_messages->listUsersMessages('me', $opt_param);
            $messages = [];

            foreach ($messages_response->getMessages() as $message) {
                $message_data = $this->service->users_messages->get('me', $message->getId(), ['format' => 'full']);
                $headers = $message_data->getPayload()->getHeaders();

                $email = [
                    'id' => $message->getId(),
                    'subject' => '',
                    'from' => '',
                    'date' => '',
                    'snippet' => $message_data->getSnippet(),
                ];

                foreach ($headers as $header) {
                    if ($header->getName() === 'Subject') {
                        $email['subject'] = $header->getValue();
                    } elseif ($header->getName() === 'From') {
                        $email['from'] = $header->getValue();
                    } elseif ($header->getName() === 'Date') {
                        $email['date'] = $header->getValue();
                    }
                }

                $messages[] = $email;
            }

            return $messages;
        } catch (Exception $e) {
            throw new Exception('Failed to list Gmail messages: ' . $e->getMessage());
        }
    }

    /**
     * Get a specific email by ID
     */
    public function get_message($message_id)
    {
        try {
            $message = $this->service->users_messages->get('me', $message_id, ['format' => 'full']);
            $payload = $message->getPayload();
            $headers = $payload->getHeaders();

            $email = [
                'id' => $message_id,
                'subject' => '',
                'from' => '',
                'to' => '',
                'date' => '',
                'body' => '',
                'attachments' => [],
            ];

            // Get header information
            foreach ($headers as $header) {
                switch ($header->getName()) {
                    case 'Subject':
                        $email['subject'] = $header->getValue();
                        break;
                    case 'From':
                        $email['from'] = $header->getValue();
                        break;
                    case 'To':
                        $email['to'] = $header->getValue();
                        break;
                    case 'Date':
                        $email['date'] = $header->getValue();
                        break;
                }
            }

            // Get message body
            $email['body'] = $this->get_message_body($payload);

            // Get attachments
            if (!empty($payload->getParts())) {
                foreach ($payload->getParts() as $part) {
                    if (!empty($part->getFilename())) {
                        $email['attachments'][] = [
                            'filename' => $part->getFilename(),
                            'mimeType' => $part->getMimeType(),
                            'attachmentId' => $part->getBody()->getAttachmentId(),
                        ];
                    }
                }
            }

            return $email;
        } catch (Exception $e) {
            throw new Exception('Failed to get Gmail message: ' . $e->getMessage());
        }
    }

    /**
     * Helper function to get message body
     */
    private function get_message_body($payload)
    {
        $body = '';

        if ($payload->getBody()->getData()) {
            $body = $this->decode_body($payload->getBody()->getData());
        } else if ($payload->getParts()) {
            foreach ($payload->getParts() as $part) {
                if ($part->getMimeType() === 'text/plain') {
                    $body = $this->decode_body($part->getBody()->getData());
                    break;
                }
            }
        }

        return $body;
    }

    /**
     * Helper function to decode message body
     */
    private function decode_body($data)
    {
        $body = str_replace(['-', '_'], ['+', '/'], $data);
        return base64_decode($body);
    }
}
