<?php

namespace App\Services;

use Illuminate\Support\Facades\Log;

/**
 * EmailService
 * 
 * Public service for other modules to send and receive emails.
 * Provides a clean, standardized interface with comprehensive error handling.
 * 
 * Usage Examples:
 * 
 * // Send a plain text email
 * $result = EmailService::send('user@example.com', 'Hello', 'This is a test email.');
 * 
 * // Send an HTML email
 * $result = EmailService::send('user@example.com', 'Welcome', '<h1>Welcome!</h1><p>Thank you for joining.</p>', true);
 * 
 * // Receive recent emails
 * $result = EmailService::receive(5);
 * 
 * Response Format:
 * [
 *     'success' => bool,
 *     'messageId' => string|null,  // For sends
 *     'message' => string,
 *     'data' => array|null,        // For receives
 *     'error' => string|null,
 *     'execution_time_ms' => int,
 * ]
 * 
 * @package App\Services
 */
class EmailService
{
    /**
     * Configuration service instance.
     *
     * @var EmailConfigurationService
     */
    protected EmailConfigurationService $configService;

    /**
     * Email provider instance.
     *
     * @var EmailProvider
     */
    protected EmailProvider $provider;

    /**
     * Create a new EmailService instance.
     */
    public function __construct(EmailConfigurationService $configService, EmailProvider $provider)
    {
        $this->configService = $configService;
        $this->provider = $provider;
    }

    /**
     * Send an email to a recipient.
     *
     * @param string $to Recipient email address
     * @param string $subject Email subject line
     * @param string $body Email body content (plain text or HTML)
     * @param bool $isHtml Whether the body is HTML (default: false)
     * @return array Standardized response
     */
    public function send(string $to, string $subject, string $body, bool $isHtml = false): array
    {
        // Validate configuration
        if (!$this->configService->isConfigured()) {
            Log::warning('EmailService: No configuration available', [
                'to' => $to,
                'subject' => $subject,
            ]);

            return [
                'success' => false,
                'messageId' => null,
                'message' => 'Email is not configured. Please contact administrator.',
                'data' => null,
                'error' => 'No active email configuration',
                'execution_time_ms' => 0,
            ];
        }

        // Validate email address
        if (!$this->provider->validateEmailAddress($to)) {
            return [
                'success' => false,
                'messageId' => null,
                'message' => 'Invalid email address provided.',
                'data' => null,
                'error' => "Invalid email: {$to}",
                'execution_time_ms' => 0,
            ];
        }

        // Sanitize subject (XSS prevention)
        $subject = strip_tags($subject);

        // Log the send attempt
        Log::info('EmailService: Sending email', [
            'to' => $to,
            'subject' => $subject,
            'is_html' => $isHtml,
        ]);

        // Send via provider
        $result = $this->provider->sendEmail($to, $subject, $body, $isHtml);

        // Return standardized response
        return [
            'success' => $result['success'],
            'messageId' => $result['messageId'] ?? null,
            'message' => $result['message'],
            'data' => null,
            'error' => $result['error'] ?? null,
            'execution_time_ms' => $result['execution_time_ms'] ?? 0,
        ];
    }

    /**
     * Send an HTML email.
     * Convenience method for sending HTML emails.
     *
     * @param string $to Recipient email address
     * @param string $subject Email subject line
     * @param string $htmlBody HTML content of the email
     * @return array Standardized response
     */
    public function sendHtml(string $to, string $subject, string $htmlBody): array
    {
        return $this->send($to, $subject, $htmlBody, true);
    }

    /**
     * Send a plain text email.
     * Convenience method for sending plain text emails.
     *
     * @param string $to Recipient email address
     * @param string $subject Email subject line
     * @param string $textBody Plain text content of the email
     * @return array Standardized response
     */
    public function sendText(string $to, string $subject, string $textBody): array
    {
        return $this->send($to, $subject, $textBody, false);
    }

    /**
     * Receive recent emails from inbox.
     *
     * @param int $limit Maximum number of emails to fetch (default: 10)
     * @return array Standardized response with emails data
     */
    public function receive(int $limit = 10): array
    {
        // Validate configuration
        if (!$this->configService->hasCredentials('imap')) {
            Log::warning('EmailService: IMAP not configured for receiving');

            return [
                'success' => false,
                'messageId' => null,
                'message' => 'IMAP is not configured for receiving emails.',
                'data' => null,
                'error' => 'No IMAP configuration',
                'execution_time_ms' => 0,
            ];
        }

        Log::info('EmailService: Receiving emails', [
            'limit' => $limit,
        ]);

        // Receive via provider
        $result = $this->provider->receiveEmails($limit);

        // Return standardized response
        return [
            'success' => $result['success'],
            'messageId' => null,
            'message' => $result['message'],
            'data' => [
                'count' => $result['count'] ?? 0,
                'emails' => $result['emails'] ?? [],
            ],
            'error' => $result['error'] ?? null,
            'execution_time_ms' => $result['execution_time_ms'] ?? 0,
        ];
    }

    /**
     * Test SMTP connection.
     * Useful for configuration validation.
     *
     * @return array Test result
     */
    public function testSmtp(): array
    {
        return $this->provider->testSmtpConnection();
    }

    /**
     * Test IMAP connection.
     * Useful for configuration validation.
     *
     * @return array Test result
     */
    public function testImap(): array
    {
        return $this->provider->testImapConnection();
    }

    /**
     * Check if email is configured and ready to use.
     *
     * @return bool
     */
    public function isReady(): bool
    {
        return $this->configService->isConfigured();
    }

    /**
     * Check if SMTP is configured.
     *
     * @return bool
     */
    public function hasSmtp(): bool
    {
        return $this->configService->hasCredentials('smtp');
    }

    /**
     * Check if IMAP is configured.
     *
     * @return bool
     */
    public function hasImap(): bool
    {
        return $this->configService->hasCredentials('imap');
    }

    /**
     * Get sender information from configuration.
     *
     * @return array|null
     */
    public function getSenderInfo(): ?array
    {
        $status = $this->configService->getStatusSummary();

        if (!$status['configured']) {
            return null;
        }

        return [
            'address' => $status['from_address'],
            'name' => $status['from_name'],
        ];
    }

    /**
     * Send email to multiple recipients.
     *
     * @param array $recipients Array of email addresses
     * @param string $subject Email subject
     * @param string $body Email body
     * @param bool $isHtml Whether body is HTML
     * @return array Results for each recipient
     */
    public function sendToMany(array $recipients, string $subject, string $body, bool $isHtml = false): array
    {
        $results = [];

        foreach ($recipients as $recipient) {
            $results[$recipient] = $this->send($recipient, $subject, $body, $isHtml);
        }

        return [
            'success' => collect($results)->where('success', true)->count() === count($recipients),
            'total' => count($recipients),
            'successful' => collect($results)->where('success', true)->count(),
            'failed' => collect($results)->where('success', false)->count(),
            'results' => $results,
        ];
    }

    /**
     * Send email using a template.
     * Renders a Blade template as the email body.
     *
     * @param string $to Recipient email address
     * @param string $subject Email subject
     * @param string $template Blade template name
     * @param array $data Data to pass to template
     * @return array Standardized response
     */
    public function sendTemplate(string $to, string $subject, string $template, array $data = []): array
    {
        try {
            $htmlBody = view($template, $data)->render();
            return $this->sendHtml($to, $subject, $htmlBody);
        } catch (\Throwable $e) {
            Log::error('EmailService: Template rendering failed', [
                'template' => $template,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'messageId' => null,
                'message' => 'Failed to render email template.',
                'data' => null,
                'error' => $e->getMessage(),
                'execution_time_ms' => 0,
            ];
        }
    }

    /**
     * Validate an email address format.
     *
     * @param string $email Email address to validate
     * @return bool
     */
    public function validateEmail(string $email): bool
    {
        return $this->provider->validateEmailAddress($email);
    }

    /**
     * Get service status and configuration summary.
     *
     * @return array
     */
    public function getStatus(): array
    {
        return [
            'configured' => $this->isReady(),
            'smtp_ready' => $this->hasSmtp(),
            'imap_ready' => $this->hasImap(),
            'sender' => $this->getSenderInfo(),
            'summary' => $this->configService->getStatusSummary(),
        ];
    }
}
