<?php

namespace GriffinForms\Includes\Integrations\SendGrid;

use GriffinForms\Settings;

/**
 * SendGrid Email Integration
 *
 * Handles configuration and management of SendGrid email delivery
 * for form notifications, autoresponders, and transactional emails.
 *
 * @since 1.0.0
 */
class Main extends \GriffinForms\Includes\Integrations\Format
{
    /**
     * Set integration metadata key prefix
     */
    protected function setMeta()
    {
        $this->meta = 'sendgrid';
        $this->id = 'sendgrid';
    }

    /**
     * Build integration metadata/info
     *
     * @return array Integration metadata
     */
    protected function buildInfo(): array
    {
        return [
            'id'       => 'sendgrid',
            'name'     => 'SendGrid',
            'category' => 'Email',
        ];
    }

    /**
     * Get current integration status
     *
     * @return array Status array
     */
    public function getStatus(): array
    {
        return [
            'configured' => $this->isConfigured(),
            'active'     => $this->isConfigured(),
            'message'    => $this->isConfigured() ? 'Configured' : 'Not configured',
        ];
    }

    /**
     * Get configuration form fields
     *
     * @return array Form field definitions
     */
    public function getConfigFields(): array
    {
        return [
            ['name' => 'sendgrid_api_key', 'label' => 'API Key', 'type' => 'password', 'required' => true],
            ['name' => 'sendgrid_from_email', 'label' => 'From Email', 'type' => 'email', 'required' => false],
            ['name' => 'sendgrid_from_name', 'label' => 'From Name', 'type' => 'text', 'required' => false],
            ['name' => 'sendgrid_reply_to_email', 'label' => 'Reply To Email', 'type' => 'email', 'required' => false],
        ];
    }

    /**
     * Validate SendGrid connection
     *
     * Makes a test API call to SendGrid's servers to verify the API key is valid.
     *
     * @return array ['success' => bool, 'message' => string]
     */
    protected function validateConnection(): array
    {
        $api_key = $this->getOption('api_key');
        return $this->validateWithSendGrid($api_key);
    }

    /**
     * Validate SendGrid API key with SendGrid's API
     *
     * Makes a test verification request to SendGrid's API
     * to ensure the API key is valid.
     *
     * @param string $api_key The SendGrid API key
     * @return array ['success' => bool, 'message' => string]
     */
    private function validateWithSendGrid(string $api_key): array
    {
        $form_id = $this->resolveFormContextId();
        // Check if SendGrid PHP SDK is available
        if (!class_exists('\SendGrid')) {
            $message = 'SendGrid PHP SDK is not installed. Please install it via Composer.';
            $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
            return [
                'success' => false,
                'message' => $message,
            ];
        }

        try {
            // Initialize SendGrid client with the API key
            $sendgrid = new \SendGrid($api_key);

            // Make a lightweight auth test call that does not require API Key Management scopes.
            // This better reflects our real-world usage where keys are often restricted to sending mail.
            $response = $sendgrid->client->user()->account()->get();

            if ($response->statusCode() == 200) {
                $message = 'SendGrid connection test successful - API key is valid.';
                $this->log->add('success', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
                return [
                    'success' => true,
                    'message' => 'SendGrid is properly configured and working correctly.',
                ];
            }

            $message = 'SendGrid API returned unexpected status code: ' . $response->statusCode();
            $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
            return [
                'success' => false,
                'message' => 'Unable to verify SendGrid API key.',
            ];
        } catch (\Exception $e) {
            // Check if it's an authentication error
            if (strpos($e->getMessage(), '401') !== false || strpos($e->getMessage(), 'Unauthorized') !== false) {
                $message = 'SendGrid authentication failed - Invalid API key.';
                $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
                return [
                    'success' => false,
                    'message' => 'Invalid SendGrid API key. Please verify your API key is correct.',
                ];
            }

            $message = 'SendGrid connection error: ' . $e->getMessage();
            $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
            return [
                'success' => false,
                'message' => 'Error connecting to SendGrid: ' . $e->getMessage(),
            ];
        }
    }

    /**
     * Check if external library is installed
     *
     * @return bool True if SendGrid PHP SDK is installed
     */
    public function isLibraryInstalled(): bool
    {
        return class_exists('\SendGrid');
    }

    /**
     * Get library installation instructions
     *
     * @return string Installation guide HTML
     */
    public function getLibraryInstructions(): string
    {
        return 'Install SendGrid PHP SDK via Composer: <code>composer require sendgrid/sendgrid</code>';
    }

    /**
     * Check if SendGrid is fully configured
     *
     * Configured means the API key is set.
     *
     * @return bool True if fully configured
     */
    public function isConfigured(): bool
    {
        $api_key = $this->settings->getOption('sendgrid_api_key');

        return !empty($api_key);
    }

    /**
     * Get configuration form HTML
     *
     * Returns HTML markup for the SendGrid configuration form
     * to be displayed in the integrations modal.
     *
     * @return string HTML form markup
     */
    public function getConfigurationFormHtml(): string
    {
        $api_key = $this->getOption('api_key', '');
        $from_email = $this->getOption('from_email', '');
        $from_name = $this->getOption('from_name', '');
        $reply_to_email = $this->getOption('reply_to_email', '');

        // Import form control factory
        $factory = new \GriffinForms\Includes\Integrations\FormControls\Factory();

        // Build form fields with factory
        $fields_html = '';

        $fields_html .= $factory->create(
            'password',
            'sendgrid_api_key',
            $api_key,
            'sendgrid',
            [
                'label' => __('API Key', 'griffinforms-form-builder'),
                'type' => 'password',
                'required' => true,
                'description' => __('Get your API Key from SendGrid Settings > API Keys', 'griffinforms-form-builder'),
            ]
        )->render();

        $fields_html .= $factory->create(
            'text',
            'sendgrid_from_email',
            $from_email,
            'sendgrid',
            [
                'label' => __('From Email', 'griffinforms-form-builder'),
                'type' => 'email',
                'required' => false,
                'description' => __('Default sender email address for form notifications', 'griffinforms-form-builder'),
            ]
        )->render();

        $fields_html .= $factory->create(
            'text',
            'sendgrid_from_name',
            $from_name,
            'sendgrid',
            [
                'label' => __('From Name', 'griffinforms-form-builder'),
                'type' => 'text',
                'required' => false,
                'description' => __('Default sender name to display in emails', 'griffinforms-form-builder'),
            ]
        )->render();

        $fields_html .= $factory->create(
            'text',
            'sendgrid_reply_to_email',
            $reply_to_email,
            'sendgrid',
            [
                'label' => __('Reply To Email', 'griffinforms-form-builder'),
                'type' => 'email',
                'required' => false,
                'description' => __('Email address for replies to notifications', 'griffinforms-form-builder'),
            ]
        )->render();

        // Use base template
        return $this->renderConfigurationFormTemplate('gf-sendgrid-config-form', 'sendgrid', $fields_html);
    }

    /**
     * Get configuration JavaScript
     *
     * Returns JavaScript code for form handling and validation
     *
     * @return string JavaScript code
     */
    public function getConfigurationJs(): string
    {
        $js = "
        /**
         * SendGrid Configuration Handler
         */
        (function() {
            const form = document.getElementById('gf-sendgrid-config-form');
            if (!form) return;

            const cancelBtn = form.querySelector('.gf-integration-btn-cancel');

            // Cancel button handler - goes back to info view
            if (cancelBtn) {
                cancelBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    window.loadIntegrationInfo('sendgrid');
                });
            }

            // Form submission handler
            form.addEventListener('submit', function(e) {
                e.preventDefault();

                const formId = window.griffinformsResolveActiveFormId ? window.griffinformsResolveActiveFormId() : null;
                // Validate required fields
                const apiKey = form.querySelector('#gf-sendgrid-sendgrid_api_key').value.trim();

                if (!apiKey) {
                    window.showIntegrationsMessage('danger', 'Please fill in all required fields');
                    return;
                }

                // Get optional fields
                const fromEmail = form.querySelector('#gf-sendgrid-sendgrid_from_email').value.trim();
                const fromName = form.querySelector('#gf-sendgrid-sendgrid_from_name').value.trim();
                const replyToEmail = form.querySelector('#gf-sendgrid-sendgrid_reply_to_email').value.trim();

                // Collect form data
                const data = {
                    action: 'saveIntegrationConfiguration',
                    integration_id: 'sendgrid',
                    nonce: window.griffinformsIntegrationsNonce || '',
                    form_id: formId || '',
                    sendgrid_api_key: apiKey,
                    sendgrid_from_email: fromEmail,
                    sendgrid_from_name: fromName,
                    sendgrid_reply_to_email: replyToEmail
                };

                // Send AJAX request
                jQuery.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: data,
                    success: function(response) {
                        if (response.success) {
                            window.showIntegrationsMessage('success', 'SendGrid configuration saved successfully');
                            setTimeout(() => {
                                window.loadIntegrationInfo('sendgrid');
                            }, 1000);
                        } else {
                            const message = (response.data && response.data.msg) ? response.data.msg : 'Failed to save configuration';
                            window.showIntegrationsMessage('danger', message);
                        }
                    },
                    error: function(xhr, status, error) {
                        console.error('SendGrid configuration error:', error);
                        window.showIntegrationsMessage('danger', 'Error saving SendGrid configuration');
                    }
                });
            });
        })();
        ";

        return $js;
    }

    /**
     * Save configuration
     *
     * Saves SendGrid configuration to WordPress options.
     * API key is required for operation.
     * From email, from name, and reply-to email are optional.
     *
     * @param array $config Configuration data
     * @return bool True if saved successfully
     */
    protected function saveConfiguration(array $config): bool
    {
        try {
            $api_key = isset($config['sendgrid_api_key']) ? sanitize_text_field($config['sendgrid_api_key']) : '';
            $from_email = isset($config['sendgrid_from_email']) ? sanitize_email($config['sendgrid_from_email']) : '';
            $from_name = isset($config['sendgrid_from_name']) ? sanitize_text_field($config['sendgrid_from_name']) : '';
            $reply_to_email = isset($config['sendgrid_reply_to_email']) ? sanitize_email($config['sendgrid_reply_to_email']) : '';

            // Validate required field
            if (empty($api_key)) {
                return false;
            }

            // Validate key format (SendGrid keys should start with 'SG.')
            if (strpos($api_key, 'SG.') !== 0) {
                return false;
            }

            // Save the API key
            $this->settings->updateOption('sendgrid_api_key', $api_key, 'mail');

            // Save optional fields
            if (!empty($from_email)) {
                $this->settings->updateOption('sendgrid_from_email', $from_email, 'mail');
            }
            if (!empty($from_name)) {
                $this->settings->updateOption('sendgrid_from_name', $from_name, 'mail');
            }
            if (!empty($reply_to_email)) {
                $this->settings->updateOption('sendgrid_reply_to_email', $reply_to_email, 'mail');
            }

            \GriffinForms\Includes\Integrations\Categories\Mailer::getInstance()->ensureActiveProvider($this->id);

            return true;
        } catch (\Exception $e) {
            $message = 'Failed to save SendGrid configuration: ' . $e->getMessage();
            $form_id = $this->resolveFormContextId();
            $this->log->add('error', 'form', $form_id, get_current_user_id(), $message, 'Mail Integration (sendgrid)');
            return false;
        }
    }

    /**
     * Custom disable logic for SendGrid
     *
     * Clears the SendGrid configuration and ensures integration is marked as disabled.
     *
     * @return void
     */
    protected function onDisable()
    {
        // No additional cleanup needed beyond clearAllOptions()
    }
}
