<?php

declare(strict_types=1);

namespace App\Framework\Notification\Channels;

use App\Domain\Common\ValueObject\Email;
use App\Framework\Mail\EmailList;
use App\Framework\Mail\MailerInterface;
use App\Framework\Mail\Message;
use App\Framework\Mail\Priority;
use App\Framework\Notification\Notification;
use App\Framework\Notification\ValueObjects\NotificationChannel;
use App\Framework\Notification\ValueObjects\NotificationPriority;

/**
 * Email notification channel
 *
 * Sends notifications via email using the framework's Mail module
 */
final readonly class EmailChannel implements NotificationChannelInterface
{
    public function __construct(
        private MailerInterface $mailer,
        private Email $fromAddress,
        private UserEmailResolver $userEmailResolver
    ) {
    }

    public function send(Notification $notification): ChannelResult
    {
        try {
            // Resolve recipient email address
            $recipientEmail = $this->userEmailResolver->resolveEmail($notification->recipientId);

            if ($recipientEmail === null) {
                return ChannelResult::failure(
                    channel: NotificationChannel::EMAIL,
                    errorMessage: "Could not resolve email for user: {$notification->recipientId}"
                );
            }

            // Build email message
            $message = new Message(
                from: $this->fromAddress,
                subject: $notification->title,
                body: $this->formatBodyAsText($notification),
                htmlBody: $this->formatBodyAsHtml($notification),
                priority: $this->mapPriority($notification->priority),
                to: new EmailList($recipientEmail)
            );

            // Send via mailer
            $result = $this->mailer->send($message);

            if ($result->success) {
                return ChannelResult::success(
                    channel: NotificationChannel::EMAIL,
                    metadata: ['message_id' => $result->messageId ?? null]
                );
            }

            return ChannelResult::failure(
                channel: NotificationChannel::EMAIL,
                errorMessage: $result->error ?? 'Unknown email delivery error'
            );
        } catch (\Throwable $e) {
            return ChannelResult::failure(
                channel: NotificationChannel::EMAIL,
                errorMessage: $e->getMessage()
            );
        }
    }

    public function supports(Notification $notification): bool
    {
        return $notification->supportsChannel(NotificationChannel::EMAIL);
    }

    public function getChannel(): NotificationChannel
    {
        return NotificationChannel::EMAIL;
    }

    private function formatBodyAsText(Notification $notification): string
    {
        $text = $notification->body . "\n\n";

        if ($notification->hasAction()) {
            $text .= "{$notification->actionLabel}: {$notification->actionUrl}\n";
        }

        $text .= "\n---\n";
        $text .= "This is an automated notification. Please do not reply to this email.\n";

        return $text;
    }

    private function formatBodyAsHtml(Notification $notification): string
    {
        $html = '<html><body>';
        $html .= '<h2>' . htmlspecialchars($notification->title) . '</h2>';
        $html .= '<p>' . nl2br(htmlspecialchars($notification->body)) . '</p>';

        if ($notification->hasAction()) {
            $html .= sprintf(
                '<p><a href="%s" style="background-color: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; display: inline-block;">%s</a></p>',
                htmlspecialchars($notification->actionUrl),
                htmlspecialchars($notification->actionLabel)
            );
        }

        $html .= '<hr>';
        $html .= '<p style="color: #666; font-size: 12px;">This is an automated notification. Please do not reply to this email.</p>';
        $html .= '</body></html>';

        return $html;
    }

    private function mapPriority(NotificationPriority $priority): Priority
    {
        return match ($priority) {
            NotificationPriority::LOW => Priority::LOW,
            NotificationPriority::NORMAL => Priority::NORMAL,
            NotificationPriority::HIGH => Priority::HIGH,
            NotificationPriority::URGENT => Priority::HIGH,
        };
    }
}
