<?php

namespace App\Services\School;

use App\Services\EmailService;
use App\Services\Notifications\UserNotificationDispatchService;
use Illuminate\Support\Facades\Log;

class EnrollmentEventService
{
    public function __construct(
        private EmailService $emailService,
        private UserNotificationDispatchService $notifier
    ) {
    }

    public function admissionUnderReview(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Admission Application Under Review',
        ];

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Admission Under Review',
            'Your admission application is under review. We will notify you once it is approved.',
            'registration'
        );

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Admission Application Under Review',
            $this->renderEmail('emails/status_admission_review', $emailData, 'Admission Application Under Review'),
            'registration'
        );
    }

    public function paymentPending(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameSentence($students, $parentData['student_name'] ?? 'your student');

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'amountDue' => $parentData['amount'] ?? '',
            'dueDate' => $parentData['due_date'] ?? '',
            'portalLink' => $parentData['paymentLink'] ?? ($parentData['portalLink'] ?? url('/login')),
            'title' => 'Admission Decision',
        ];

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Payment Pending',
            'Your payment is pending. Please check your email for details.',
            'payment'
        );

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Admission Decision',
            $this->renderEmail('emails/status_payment_pending', $emailData, 'Admission Decision'),
            'payment'
        );
    }

    public function studentEnrolled(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentsDetails = $this->studentDetails($students);
        $studentNameData = $this->studentNameData($students, $parentData);
        $first = $studentsDetails[0] ?? [];

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $parentData['student_name'] ?? $studentNameData,
            'schoolYear' => $parentData['school_year'] ?? date('Y'),
            'studentId' => $parentData['student_id'] ?? ($first['studentId'] ?? ''),
            'gradeLevel' => $parentData['grade_level'] ?? ($first['gradeLevel'] ?? ''),
            'teacherName' => $parentData['teacher_name'] ?? ($first['teacherName'] ?? ''),
            'startDate' => $parentData['start_date'] ?? ($first['startDate'] ?? ''),
            'students' => count($studentsDetails) > 1 ? $studentsDetails : null,
            'portalLink' => url('/login'),
            'title' => 'Enrollment Confirmation',
        ];

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Enrollment Confirmed',
            'Enrollment confirmed. Please check your email for details.',
            'registration'
        );

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Enrollment Confirmation',
            $this->renderEmail('emails/status_enrolled', $emailData, 'Enrollment Confirmation'),
            'registration'
        );
    }

    public function withdrawUnderReview(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Withdrawal Request Received',
            'Your withdrawal request is under review. Please check your email for details.',
            'registration'
        );

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $parentData['student_name'] ?? $studentName,
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Withdrawal Under Review',
        ];

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Withdrawal Request Under Review',
            $this->renderEmail('emails/status_withdraw_review', $emailData, 'Withdrawal Request Under Review'),
            'registration'
        );
    }

    public function refundPending(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Refund Pending',
            'A refund is being processed. Please check your email for details.',
            'payment'
        );

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'refundAmount' => $parentData['amount'] ?? '',
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Refund Pending',
        ];

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Refund Pending',
            $this->renderEmail('emails/status_refund_pending', $emailData, 'Refund Pending'),
            'payment'
        );
    }

    public function withdrawn(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);
        $withdrawals = $this->withdrawalsList($students);

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Withdrawal Confirmed',
            'Your withdrawal has been completed. Please check your email for details.',
            'registration'
        );

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'withdrawalDate' => $parentData['withdrawal_date'] ?? ($parentData['date'] ?? ''),
            'withdrawals' => !empty($withdrawals) ? $withdrawals : null,
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Withdrawal Confirmed',
        ];

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Withdrawal Confirmed',
            $this->renderEmail('emails/status_withdrawn', $emailData, 'Withdrawal Confirmed'),
            'registration'
        );
    }

    public function denied(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);
        $studentsWithReasons = $this->studentsWithReasons($students);

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Admission Decision',
            'We\'ve emailed you an update regarding your admission decision.',
            'registration'
        );

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'students' => $studentsWithReasons ?: null,
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Admission Decision',
        ];

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Admission Decision',
            $this->renderEmail('emails/status_denied', $emailData, 'Admission Decision'),
            'registration'
        );
    }

    public function waitlist(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);
        $studentName = $this->studentNameData($students, $parentData);

        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Waitlist Update',
            'Your application is currently on the waitlist. Please check your email for details.',
            'registration'
        );

        $emailData = [
            'parentName' => $parentName,
            'studentName' => $studentName,
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Waitlist Update',
        ];

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Admission Decision',
            $this->renderEmail('emails/status_waitlist', $emailData, 'Admission Decision'),
            'registration'
        );
    }

    public function enrollmentStatusChanged(array $parentData, array $students): array
    {
        $parentName = $this->parentName($parentData);

        $emailData = [
            'parentName' => $parentName,
            'schoolYear' => $parentData['school_year'] ?? '',
            'changes' => $parentData['changes'] ?? [],
            'portalLink' => $parentData['portalLink'] ?? url('/login'),
            'title' => 'Enrollment Status Update',
        ];

        $summaryCount = count($emailData['changes']);
        $this->notifyParent(
            (int) ($parentData['user_id'] ?? 0),
            'Enrollment Status Updated',
            "Enrollment status updated for {$summaryCount} student(s). Check your email for details.",
            'registration'
        );

        return $this->sendEmail(
            (string) ($parentData['email'] ?? ''),
            'Enrollment Status Update',
            $this->renderEmail('emails/status_enrollment_batch', $emailData, 'Enrollment Status Update'),
            'registration'
        );
    }

    private function parentName(array $parentData): string
    {
        return trim((string) ($parentData['firstname'] ?? '') . ' ' . (string) ($parentData['lastname'] ?? ''));
    }

    private function studentNameData(array $studentdata, array $parentData)
    {
        $names = [];
        foreach ($studentdata as $s) {
            $nm = !empty($s['name'])
                ? trim((string) $s['name'])
                : trim((string) ($s['firstname'] ?? '') . ' ' . (string) ($s['lastname'] ?? ''));
            if ($nm !== '') {
                $names[] = $nm;
            }
        }

        if (empty($names)) {
            return $parentData['student_name'] ?? 'your student';
        }
        if (count($names) === 1) {
            return $names[0];
        }
        return $names;
    }

    private function studentNameSentence(array $studentdata, string $fallback): string
    {
        $names = [];
        foreach ($studentdata as $s) {
            $nm = !empty($s['name'])
                ? trim((string) $s['name'])
                : trim((string) ($s['firstname'] ?? '') . ' ' . (string) ($s['lastname'] ?? ''));
            if ($nm !== '') {
                $names[] = $nm;
            }
        }

        if (count($names) === 0) {
            return $fallback;
        }
        if (count($names) === 1) {
            return $names[0];
        }
        if (count($names) === 2) {
            return $names[0] . ' and ' . $names[1];
        }
        $last = array_pop($names);
        return implode(', ', $names) . ', and ' . $last;
    }

    private function studentDetails(array $studentdata): array
    {
        $details = [];
        foreach ($studentdata as $s) {
            $nm = !empty($s['name'])
                ? trim((string) $s['name'])
                : trim((string) ($s['firstname'] ?? '') . ' ' . (string) ($s['lastname'] ?? ''));
            if ($nm === '') {
                continue;
            }
            $details[] = [
                'name' => $nm,
                'studentId' => $s['student_id'] ?? $s['id'] ?? '',
                'gradeLevel' => $s['grade_level'] ?? $s['grade'] ?? '',
                'teacherName' => $s['teacher_name'] ?? $s['teacher'] ?? '',
                'startDate' => $s['start_date'] ?? '',
            ];
        }
        return $details;
    }

    private function withdrawalsList(array $studentdata): array
    {
        $withdrawals = [];
        foreach ($studentdata as $s) {
            $nm = !empty($s['name'])
                ? trim((string) $s['name'])
                : trim((string) ($s['firstname'] ?? '') . ' ' . (string) ($s['lastname'] ?? ''));
            if ($nm === '') {
                continue;
            }
            $wd = $s['withdrawal_date'] ?? $s['date'] ?? null;
            if ($wd) {
                $withdrawals[] = [
                    'name' => $nm,
                    'withdrawalDate' => $wd,
                ];
            }
        }
        return $withdrawals;
    }

    private function studentsWithReasons(array $studentdata): array
    {
        $rows = [];
        foreach ($studentdata as $s) {
            $nm = !empty($s['name'])
                ? trim((string) $s['name'])
                : trim((string) ($s['firstname'] ?? '') . ' ' . (string) ($s['lastname'] ?? ''));
            if ($nm === '') {
                continue;
            }
            $rows[] = [
                'name' => $nm,
                'reason' => $s['reason'] ?? null,
            ];
        }
        return $rows;
    }

    private function notifyParent(int $userId, string $title, string $message, string $topic): void
    {
        if ($userId <= 0) {
            return;
        }
        $this->notifier->notifyUser($userId, $title, $message, ['in_app'], $topic, 'parent');
    }

    private function sendEmail(string $to, string $subject, string $html, string $fromKey): array
    {
        if ($to === '') {
            Log::warning('Enrollment event: missing recipient email', ['subject' => $subject]);
            return ['ok' => false, 'message' => 'Missing recipient email.'];
        }

        $ok = $this->emailService->send($to, $subject, $html, $fromKey);
        if (!$ok) {
            Log::error('Enrollment event email failed', ['to' => $to, 'subject' => $subject]);
        }
        return ['ok' => $ok];
    }

    private function renderEmail(string $viewName, array $data, string $fallbackTitle): string
    {
        try {
            return view($viewName, $data, ['saveData' => true]);
        } catch (\Throwable $e) {
            return '<p>' . e($fallbackTitle) . '</p>';
        }
    }
}
