<?php

declare(strict_types=1);

namespace App\Libraries;

use App\Models\BookingSmtpConfigModel;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
use Throwable;

class BookingMailer
{
    private array $config = [];
    private bool $configured = false;

    public function __construct(?array $overrideConfig = null)
    {
        if (is_array($overrideConfig)) {
            $this->config = $overrideConfig;
            $this->configured = !empty($this->config['smtp_host'])
                && !empty($this->config['smtp_user'])
                && !empty($this->config['smtp_pass']);
            return;
        }
        try {
            $cfg = new BookingSmtpConfigModel();
            $this->config = $cfg->getAll();
            $this->configured = !empty($this->config['smtp_host'])
                && !empty($this->config['smtp_user'])
                && !empty($this->config['smtp_pass']);
        } catch (Throwable $e) {
            $this->configured = false;
            $this->config = [];
        }
    }

    public function isConfigured(): bool
    {
        return $this->configured;
    }

    public function sendBookingNotification(
        array $booking,
        string $type = 'new',
        array $toUsers = [],
        bool $toLead = false
    ): array {
        if (!$this->configured) {
            return ['ok' => false, 'msg' => 'SMTP not configured'];
        }

        $mail = new PHPMailer(true);

        try {
            $host = (string)($this->config['smtp_host'] ?? '');
            $port = (int)($this->config['smtp_port'] ?? 587);
            $user = (string)($this->config['smtp_user'] ?? '');
            $pass = (string)($this->config['smtp_pass'] ?? '');
            $secure = strtolower((string)($this->config['smtp_secure'] ?? 'tls'));
            $auth   = (bool)($this->config['smtp_auth'] ?? true);
            $fromName  = (string)($this->config['smtp_from_name'] ?? '');
            $fromEmail = (string)($this->config['smtp_from_email'] ?? '');
            $logoUrl   = (string)($this->config['email_logo_url'] ?? '');
            $locationUrl = (string)($this->config['booking_default_location_url'] ?? '');

            $mail->isSMTP();
            $mail->Host       = $host;
            $mail->SMTPAuth   = $auth;
            $mail->Username   = $user;
            $mail->Password   = $pass;
            $mail->Port       = $port;

            if ($secure === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
            } elseif ($secure === 'starttls' || $secure === 'tls') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            }

            if ($fromEmail !== '') {
                $mail->setFrom($fromEmail, $fromName);
            } else {
                $mail->setFrom($user, $fromName);
            }

            $recipients = 0;
            foreach ($toUsers as $u) {
                $email = '';
                $name = '';
                if (is_array($u)) {
                    $email = (string)($u['email'] ?? '');
                    $name  = (string)($u['full_name'] ?? $u['name'] ?? '');
                } elseif (is_object($u)) {
                    $email = (string)($u->email ?? '');
                    $name  = (string)($u->full_name ?? $u->name ?? '');
                } else {
                    $email = (string)$u;
                }
                if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL)) {
                    $mail->addAddress($email, $name);
                    $recipients++;
                }
            }

            if ($toLead) {
                $leadEmail = (string)($booking['guest_email'] ?? '');
                if ($leadEmail === '') {
                    $leadEmail = (string)($booking['email'] ?? '');
                }
                if ($leadEmail !== '' && filter_var($leadEmail, FILTER_VALIDATE_EMAIL)) {
                    $leadFrom = (string)($this->config['notify_lead_from_email'] ?? '');
                    if ($leadFrom !== '' && filter_var($leadFrom, FILTER_VALIDATE_EMAIL)) {
                        $mail->clearFrom();
                        $mail->setFrom($leadFrom, $fromName);
                    }
                    $guestName = (string)($booking['guest_name'] ?? '');
                    $mail->addAddress($leadEmail, $guestName);
                    $recipients++;
                }
            }

            if ($recipients === 0) {
                return ['ok' => false, 'msg' => 'No valid recipients'];
            }

            $titleMap = [
                'new'         => 'New Booking Confirmation',
                'cancelled'   => 'Booking Cancelled',
                'rescheduled' => 'Booking Rescheduled',
            ];
            $subject = $titleMap[$type] ?? 'Booking Update';

            $startsAt = (string)($booking['starts_at'] ?? '');
            $endsAt   = (string)($booking['ends_at'] ?? '');
            $duration = (int)($booking['duration_minutes'] ?? 0);
            $agent    = (string)($booking['agent_name'] ?? ($booking['assigned_agent_id'] ?? ''));
            $notes    = (string)($booking['notes'] ?? '');
            $guestName  = (string)($booking['guest_name'] ?? '');
            $guestPhone = (string)($booking['guest_phone'] ?? '');
            $calLink  = (string)($booking['cal_link'] ?? '');

            $bookingTimezone = (string)($booking['timezone'] ?? '');
            $bookingStatus = (string)($booking['status'] ?? 'booked');
            $notesHtml = $notes !== '' ? '<div class="notes"><strong>Notes:</strong><br>' . nl2br(htmlspecialchars($notes, ENT_QUOTES)) . '</div>' : '';
            $logoHtml = $logoUrl !== '' ? '<img src="' . htmlspecialchars($logoUrl, ENT_QUOTES) . '" alt="Logo" style="max-width:200px; margin-bottom:16px;">' : '';
            $locationHtml = $locationUrl !== '' ? '<p><strong>Location/Meeting URL:</strong> <a href="' . htmlspecialchars($locationUrl, ENT_QUOTES) . '">' . htmlspecialchars($locationUrl, ENT_QUOTES) . '</a></p>' : '';
            $calHtml = $calLink !== '' ? '<p><strong>Calendar Link:</strong> <a href="' . htmlspecialchars($calLink, ENT_QUOTES) . '">Add to Calendar</a></p>' : '';

            $body = <<<HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{$subject}</title>
    <style>
        body { font-family: Arial, sans-serif; color: #333; line-height: 1.6; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { border-bottom: 2px solid #4a90e2; padding-bottom: 16px; margin-bottom: 24px; }
        h1 { color: #4a90e2; margin: 0; font-size: 22px; }
        .card { background: #f8f9fa; border-radius: 8px; padding: 20px; margin-bottom: 16px; }
        .detail-row { display: flex; padding: 6px 0; border-bottom: 1px solid #e9ecef; }
        .detail-row:last-child { border-bottom: none; }
        .detail-label { font-weight: bold; width: 180px; color: #555; }
        .detail-value { flex: 1; }
        .notes { background: #fff3cd; padding: 12px; border-radius: 6px; margin-top: 12px; }
        a { color: #4a90e2; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            {$logoHtml}
            <h1>{$subject}</h1>
        </div>
        <div class="card">
            <h2 style="margin-top:0;">Booking Details</h2>
            <div class="detail-row"><div class="detail-label">Date &amp; Time:</div><div class="detail-value">{$startsAt} - {$endsAt}</div></div>
            <div class="detail-row"><div class="detail-label">Timezone:</div><div class="detail-value">{$bookingTimezone}</div></div>
            <div class="detail-row"><div class="detail-label">Duration:</div><div class="detail-value">{$duration} minutes</div></div>
            <div class="detail-row"><div class="detail-label">Agent:</div><div class="detail-value">{$agent}</div></div>
            <div class="detail-row"><div class="detail-label">Guest Name:</div><div class="detail-value">{$guestName}</div></div>
            <div class="detail-row"><div class="detail-label">Guest Phone:</div><div class="detail-value">{$guestPhone}</div></div>
            <div class="detail-row"><div class="detail-label">Status:</div><div class="detail-value">{$bookingStatus}</div></div>
            {$locationHtml}
            {$calHtml}
            {$notesHtml}
        </div>
    </div>
</body>
</html>
HTML;

            $mail->isHTML(true);
            $mail->Subject = $subject;
            $mail->Body    = $body;
            $mail->AltBody = strip_tags($body);

            $mail->send();
            return ['ok' => true, 'msg' => 'Email sent to ' . $recipients . ' recipient(s)'];
        } catch (PHPMailerException $e) {
            return ['ok' => false, 'msg' => 'PHPMailer error: ' . $mail->ErrorInfo];
        } catch (Throwable $e) {
            return ['ok' => false, 'msg' => 'Error: ' . $e->getMessage()];
        }
    }

    public function testConnection(): array
    {
        if (empty($this->config['smtp_host'])) {
            return ['ok' => false, 'msg' => 'SMTP host not provided.'];
        }
        $mail = new PHPMailer(true);
        try {
            $host   = (string)($this->config['smtp_host'] ?? '');
            $port   = (int)($this->config['smtp_port'] ?? 587);
            $user   = (string)($this->config['smtp_user'] ?? '');
            $pass   = (string)($this->config['smtp_pass'] ?? '');
            $secure = strtolower((string)($this->config['smtp_secure'] ?? ($this->config['smtp_encryption'] ?? 'tls')));
            $auth   = (bool)($this->config['smtp_auth'] ?? true);

            $mail->isSMTP();
            $mail->Host       = $host;
            $mail->SMTPAuth   = $auth;
            $mail->Username   = $user;
            $mail->Password   = $pass;
            $mail->Port       = $port;
            $mail->Timeout    = 15;
            if ($secure === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
            } elseif ($secure === 'starttls' || $secure === 'tls') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            }
            if (!$mail->smtpConnect()) {
                return ['ok' => false, 'msg' => 'SMTP connect failed: ' . $mail->ErrorInfo];
            }
            $mail->smtpClose();
            return ['ok' => true, 'msg' => 'SMTP connection successful.'];
        } catch (PHPMailerException $e) {
            return ['ok' => false, 'msg' => 'SMTP error: ' . $mail->ErrorInfo];
        } catch (Throwable $e) {
            return ['ok' => false, 'msg' => 'Error: ' . $e->getMessage()];
        }
    }

    public function sendTestMail(string $toEmail): array
    {
        if (!$this->configured) {
            return ['ok' => false, 'msg' => 'SMTP is not configured.'];
        }
        $mail = new PHPMailer(true);
        try {
            $host   = (string)($this->config['smtp_host'] ?? '');
            $port   = (int)($this->config['smtp_port'] ?? 587);
            $user   = (string)($this->config['smtp_user'] ?? '');
            $pass   = (string)($this->config['smtp_pass'] ?? '');
            $secure = strtolower((string)($this->config['smtp_secure'] ?? ($this->config['smtp_encryption'] ?? 'tls')));
            $auth   = (bool)($this->config['smtp_auth'] ?? true);
            $fromName  = (string)($this->config['smtp_from_name'] ?? 'Outbound CRM');
            $fromEmail = (string)($this->config['smtp_from_email'] ?? '');
            $mail->isSMTP();
            $mail->Host       = $host;
            $mail->SMTPAuth   = $auth;
            $mail->Username   = $user;
            $mail->Password   = $pass;
            $mail->Port       = $port;
            if ($secure === 'ssl') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
            } elseif ($secure === 'starttls' || $secure === 'tls') {
                $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
            }
            if ($fromEmail !== '' && filter_var($fromEmail, FILTER_VALIDATE_EMAIL)) {
                $mail->setFrom($fromEmail, $fromName);
            } elseif (filter_var($user, FILTER_VALIDATE_EMAIL)) {
                $mail->setFrom($user, $fromName);
            }
            $mail->addAddress($toEmail);
            $mail->isHTML(true);
            $mail->Subject = 'Booking SMTP — Test Message';
            $mail->Body    = '<p style="font-family:Arial,sans-serif;">If you received this, your Booking SMTP configuration works. 🎉</p>';
            $mail->AltBody = 'If you received this, your Booking SMTP configuration works.';
            $mail->send();
            return ['ok' => true, 'msg' => "Test email sent to {$toEmail}."];
        } catch (PHPMailerException $e) {
            return ['ok' => false, 'msg' => 'PHPMailer error: ' . $mail->ErrorInfo];
        } catch (Throwable $e) {
            return ['ok' => false, 'msg' => 'Error: ' . $e->getMessage()];
        }
    }

    public function notifyBookingCreated(array $booking, ?array $lead = null, ?array $agent = null, ?array $bookedBy = null, ?array $notifyAgentIds = null, ?array $notifyAdminIds = null, bool $toLeadEnabled = false): array
    {
        if (!$this->configured) return ['ok' => false, 'msg' => 'SMTP not configured'];

        $agentEmailUsers = [];
        $userModel = null;
        if (is_array($notifyAgentIds) || is_array($notifyAdminIds)) {
            try {
                $userModel = new \App\Models\UserModel();
            } catch (Throwable $e) { $userModel = null; }
        }
        if (is_array($notifyAgentIds) && $userModel !== null) {
            foreach ($notifyAgentIds as $uid) {
                $u = $userModel->find((int)$uid);
                if ($u) $agentEmailUsers[] = $u;
            }
        }
        if (is_array($notifyAdminIds) && $userModel !== null) {
            foreach ($notifyAdminIds as $uid) {
                $u = $userModel->find((int)$uid);
                if ($u) $agentEmailUsers[] = $u;
            }
        }
        if (is_array($agent)) $agentEmailUsers[] = $agent;
        if (is_array($bookedBy) && !in_array($bookedBy, $agentEmailUsers, true)) $agentEmailUsers[] = $bookedBy;

        $usersResult = $this->sendBookingNotification($booking, 'new', $agentEmailUsers, false);

        $leadResult = null;
        if ($toLeadEnabled) {
            $leadResult = $this->sendBookingNotification($booking, 'new', [], true);
        }
        return [
            'ok' => $usersResult['ok'] || ($leadResult['ok'] ?? false),
            'users_sent' => $usersResult['ok'],
            'users_msg'  => $usersResult['msg'],
            'lead_sent'  => $leadResult['ok'] ?? false,
            'lead_msg'   => $leadResult['msg'] ?? 'not enabled',
        ];
    }

    public function notifyBookingCancelled(array $booking, ?array $lead = null, ?array $agent = null, ?array $notifyAgentIds = null, ?array $notifyAdminIds = null, bool $toLeadEnabled = false): array
    {
        return $this->notifyBookingCreated($booking, $lead, $agent, null, $notifyAgentIds, $notifyAdminIds, $toLeadEnabled) + ['cancel' => true];
    }
}
