<?php

namespace App\Services\Alerts;

use App\Models\AlertLog;
use App\Models\EmailLog;
use App\Services\Mail\MailSettingsManager;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Mail;
use Throwable;

class AlertNotificationService
{
    public function __construct(private readonly MailSettingsManager $settingsManager)
    {
    }

    public function send(AlertLog $alertLog): EmailLog
    {
        $alertLog->loadMissing(['client', 'rule']);

        $recipients = $this->resolveRecipients($alertLog);
        $subject = '[' . strtoupper($alertLog->severity) . '] ' . $alertLog->title;

        $emailLog = EmailLog::create([
            'client_id' => $alertLog->client_id,
            'subject' => $subject,
            'recipients' => $recipients,
            'status' => 'queued',
            'meta' => [
                'type' => 'alert',
                'alert_log_id' => $alertLog->id,
                'alert_rule_id' => $alertLog->alert_rule_id,
            ],
        ]);

        if ($recipients === []) {
            $emailLog->update([
                'status' => 'failed',
                'error_message' => 'Uyarı bildirimi için alıcı bulunamadı.',
            ]);

            return $emailLog;
        }

        try {
            $this->settingsManager->apply();
            $settings = $this->settingsManager->all();

            Mail::send('emails.alerts.triggered', ['alertLog' => $alertLog], function ($message) use ($subject, $recipients, $settings) {
                $message->to($recipients)->subject($subject);

                if (filled($settings['from_email'] ?? null)) {
                    $message->from($settings['from_email'], $settings['from_name'] ?? null);
                }

                if (filled($settings['reply_to'] ?? null)) {
                    $message->replyTo($settings['reply_to']);
                }
            });

            $emailLog->update([
                'status' => 'sent',
                'sent_at' => now(),
            ]);

            $alertLog->update(['notified_at' => now()]);
        } catch (Throwable $exception) {
            report($exception);

            $emailLog->update([
                'status' => 'failed',
                'error_message' => $exception->getMessage(),
            ]);
        }

        return $emailLog->refresh();
    }

    /**
     * @return array<int, string>
     */
    private function resolveRecipients(AlertLog $alertLog): array
    {
        $ruleEmails = Arr::wrap($alertLog->rule?->notification_emails ?: []);
        $clientRecipients = Arr::wrap($alertLog->client?->report_recipients ?: []);
        $clientEmail = $alertLog->client?->email ? [$alertLog->client->email] : [];

        return collect([...$ruleEmails, ...$clientRecipients, ...$clientEmail])
            ->flatMap(fn ($item) => preg_split('/\r\n|\r|\n|,|;/', (string) $item) ?: [])
            ->map(fn ($email) => trim((string) $email))
            ->filter(fn ($email) => filter_var($email, FILTER_VALIDATE_EMAIL))
            ->unique()
            ->values()
            ->all();
    }
}
