<?php

namespace App\Services\Settings\SchoolCalendar;

use App\Models\User;
use App\Services\ApplicationUrlService;
use App\Services\EmailService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SchoolCalendarNotificationService
{
    public function __construct(
        private EmailService $emailService,
        private ApplicationUrlService $urls,
    ) {
    }

    public function notify(array $event, array $targets): array
    {
        if (empty($event) || empty(array_filter($targets))) {
            return [];
        }

        $subject = $this->buildSubject($event);
        $body = $this->buildBody($event);

        $results = [];
        foreach ($targets as $group => $enabled) {
            if (!$enabled) {
                continue;
            }

            $emails = $this->collectEmailsForGroup($group);
            if (empty($emails)) {
                Log::warning("SchoolCalendar: no recipient emails for {$group}.");
                $results[$group] = null;
                continue;
            }

            $to = $emails[0] ?? '';
            $ok = $this->emailService->send($to, $subject, $body, 'general', [], $emails);
            if (!$ok) {
                Log::warning("SchoolCalendar: failed to send calendar notification to {$group}.");
            }
            $results[$group] = $ok;
        }

        return $results;
    }

    private function buildSubject(array $event): string
    {
        $title = trim((string) ($event['title'] ?? 'School Calendar Update'));
        $typeSegment = !empty($event['event_type']) ? ' (' . $event['event_type'] . ')' : '';
        return 'School Calendar: ' . $title . $typeSegment;
    }

    private function buildBody(array $event): string
    {
        $calendarUrl = $this->urls->spaAdministratorCalendarViewUrl();
        $title = trim((string) ($event['title'] ?? 'School Calendar Update'));
        $date = (string) ($event['date'] ?? '');
        $description = trim((string) ($event['description'] ?? ''));

        $body = '<h3>' . e($title) . '</h3>';
        $body .= '<p><strong>Date:</strong> ' . e($date) . '</p>';
        if ($description !== '') {
            $body .= '<p>' . nl2br(e($description)) . '</p>';
        }
        $body .= '<p><a href="' . e($calendarUrl) . '">View calendar</a></p>';

        return $body;
    }

    private function collectEmailsForGroup(string $group): array
    {
        return match ($group) {
            'parents' => $this->normalizeEmails(User::getParents()),
            'teachers' => $this->normalizeEmails(User::getAllTeachers()),
            'admins' => $this->normalizeEmails($this->fetchAdminRows()),
            default => [],
        };
    }

    private function normalizeEmails(array $rows): array
    {
        $emails = [];
        foreach ($rows as $row) {
            $email = trim((string) ($row['email'] ?? ''));
            if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
                continue;
            }
            $emails[$email] = true;
        }
        return array_values(array_keys($emails));
    }

    private function fetchAdminRows(): array
    {
        $excluded = ['guest', 'teacher', 'teacher_assistant', 'parent'];
        $escaped = array_map(static fn ($value) => "'" . addslashes($value) . "'", $excluded);
        $excludedList = implode(', ', $escaped);

        $builder = DB::table('users as u')
            ->selectRaw("u.id, u.firstname, u.lastname, u.email, MAX(CASE WHEN LOWER(COALESCE(r.slug, r.name)) NOT IN({$excludedList}) THEN 1 ELSE 0 END) AS is_admin")
            ->join('user_roles as ur', 'ur.user_id', '=', 'u.id')
            ->join('roles as r', 'r.id', '=', 'ur.role_id')
            ->where('r.is_active', 1)
            ->whereNotNull('u.email')
            ->where('u.email', '!=', '')
            ->groupBy('u.id', 'u.firstname', 'u.lastname', 'u.email')
            ->having('is_admin', 1);

        return $builder->get()->map(fn ($r) => (array) $r)->all();
    }
}
