<?php

namespace App\Services;

use App\Models\Member;
use App\Models\Contribution;
use App\Models\LoanApplication;
use App\Models\LoanRepayment;
use App\Models\MembershipApplication;
use App\Models\SelfPaced\Enrollment;
use App\Models\TrainingCertificate;
use App\Models\TrainingRegistration;
use App\Models\TrainingSession;
use Illuminate\Support\Facades\Log;

class NotificationService
{
    protected SMSService $smsService;
    protected EmailService $emailService;

    public function __construct(SMSService $smsService, EmailService $emailService)
    {
        $this->smsService = $smsService;
        $this->emailService = $emailService;
    }

    /**
     * Send welcome notification to new member.
     */
    public function sendWelcome(Member $member): void
    {
        $user = $member->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'membership_code' => $member->membership_code,
            'login_url' => route('login'),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Welcome to ' . config('app.name'),
                'emails.membership.welcome',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Welcome to " . config('app.name') . "! Your membership code is {$member->membership_code}. Login at " . route('login');
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send membership application confirmation.
     */
    public function sendApplicationConfirmation(MembershipApplication $application): void
    {
        $data = [
            'name' => $application->full_name,
            'reference_number' => $application->reference_number,
            'category' => $application->membershipCategory->name,
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $application->email,
                'Membership Application Received',
                'emails.membership.application-received',
                $data
            );
        }

        if ($application->phone && $this->smsService->isAvailable()) {
            $message = "Your membership application has been received. Reference: {$application->reference_number}";
            $this->smsService->send($application->phone, $message);
        }
    }

    /**
     * Send application status update notification.
     */
    public function sendApplicationStatusUpdate(MembershipApplication $application): void
    {
        $user = $application->user;

        if (!$user) {
            return;
        }

        $status = ucfirst($application->status);
        $data = [
            'name' => $application->full_name,
            'reference_number' => $application->reference_number,
            'status' => $status,
            'membership_code' => $application->member?->membership_code,
            'rejection_reason' => $application->rejection_reason,
        ];

        if ($this->emailService->isReady()) {
            $template = $application->status === 'approved'
                ? 'emails.membership.application-approved'
                : 'emails.membership.application-status';

            $this->emailService->sendTemplate(
                $application->email,
                "Membership Application {$status}",
                $template,
                $data
            );
        }

        if ($application->phone && $this->smsService->isAvailable()) {
            if ($application->status === 'approved') {
                $message = "Congratulations! Your membership application has been approved. Your membership code is {$application->member->membership_code}";
            } else {
                $message = "Your membership application status: {$status}. Reference: {$application->reference_number}";
            }
            $this->smsService->send($application->phone, $message);
        }
    }

    /**
     * Send contribution confirmation.
     */
    public function sendContributionConfirmation(Contribution $contribution): void
    {
        $member = $contribution->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => $contribution->formatted_amount,
            'period' => $contribution->period,
            'reference' => $contribution->reference_number,
            'date' => $contribution->paid_date?->format('F j, Y'),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Contribution Payment Received',
                'emails.contributions.payment-confirmation',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Payment received! {$contribution->formatted_amount} for {$contribution->period}. Ref: {$contribution->reference_number}";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send contribution reminder.
     */
    public function sendContributionReminder(Contribution $contribution): void
    {
        $member = $contribution->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => $contribution->formatted_amount,
            'period' => $contribution->period,
            'due_date' => $contribution->due_date->format('F j, Y'),
            'days_remaining' => now()->diffInDays($contribution->due_date, false),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Contribution Payment Reminder',
                'emails.contributions.reminder',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $daysText = $data['days_remaining'] > 0 ? "in {$data['days_remaining']} days" : 'today';
            $message = "Reminder: Contribution of {$contribution->formatted_amount} for {$contribution->period} is due {$daysText}.";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send overdue contribution notice.
     */
    public function sendOverdueNotice(Contribution $contribution): void
    {
        $member = $contribution->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => $contribution->formatted_amount,
            'penalty_amount' => $contribution->penalty_amount,
            'total_amount' => $contribution->total_amount,
            'period' => $contribution->period,
            'days_overdue' => $contribution->getDaysOverdue(),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Overdue Contribution Notice',
                'emails.contributions.overdue',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "OVERDUE: Your contribution of {$contribution->formatted_amount} is {$contribution->getDaysOverdue()} days overdue. Please pay to avoid additional penalties.";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Notify managers of new loan application.
     */
    public function notifyManagersOfNewLoanApplication(LoanApplication $application): void
    {
        $managers = \App\Models\User::whereHas('roles', function ($query) {
            $query->whereIn('name', ['Manager', 'Super Manager']);
        })->get();

        foreach ($managers as $manager) {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $manager->email,
                    'New Loan Application',
                    'emails.loans.new-application',
                    [
                        'manager_name' => $manager->name,
                        'applicant_name' => $application->applicant_name,
                        'amount' => $application->amount_requested,
                        'product' => $application->loanProduct->name,
                        'reference' => $application->reference_number,
                    ]
                );
            }
        }
    }

    /**
     * Notify member of loan approval.
     */
    public function notifyMemberLoanApproved(LoanApplication $application): void
    {
        $member = $application->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => number_format($application->amount_approved, 2),
            'currency' => $application->currency,
            'reference' => $application->reference_number,
            'term_months' => $application->term_months,
            'monthly_payment' => number_format($application->monthly_payment, 2),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Loan Application Approved',
                'emails.loans.approved',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Good news! Your loan application of {$data['currency']} {$data['amount']} has been approved. Monthly payment: {$data['currency']} {$data['monthly_payment']}";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Notify member of loan rejection.
     */
    public function notifyMemberLoanRejected(LoanApplication $application): void
    {
        $member = $application->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => number_format($application->amount_requested, 2),
            'currency' => $application->currency,
            'reference' => $application->reference_number,
            'reason' => $application->rejection_reason,
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Loan Application Update',
                'emails.loans.rejected',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Your loan application (Ref: {$application->reference_number}) has been reviewed. Please check your email for details.";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send loan repayment confirmation.
     */
    public function sendLoanRepaymentConfirmation(LoanRepayment $repayment): void
    {
        $application = $repayment->loanApplication;
        $member = $application->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => number_format($repayment->amount_paid, 2),
            'currency' => $application->currency,
            'outstanding' => number_format($application->outstanding_balance, 2),
            'reference' => $repayment->reference_number,
            'installment' => $repayment->installment_number,
            'total_installments' => $application->term_months,
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Loan Payment Received',
                'emails.loans.repayment-confirmation',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Payment received! {$data['currency']} {$data['amount']}. Outstanding balance: {$data['currency']} {$data['outstanding']}";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send loan disbursement notification.
     */
    public function sendDisbursementNotification(LoanApplication $application, float $disbursedAmount): void
    {
        $member = $application->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'amount' => number_format($disbursedAmount, 2),
            'currency' => $application->currency,
            'reference' => $application->reference_number,
            'monthly_payment' => number_format($application->monthly_payment, 2),
            'first_payment_date' => $application->next_payment_date?->format('F j, Y'),
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Loan Disbursed',
                'emails.loans.disbursed',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Loan disbursed! {$data['currency']} {$data['amount']} has been sent to your account. First payment of {$data['currency']} {$data['monthly_payment']} is due on {$data['first_payment_date']}.";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send membership renewal reminder.
     */
    public function sendRenewalReminder(Member $member, int $daysUntilExpiry): void
    {
        $user = $member->user;

        if (!$user) {
            return;
        }

        $data = [
            'name' => $user->name,
            'membership_code' => $member->membership_code,
            'expiry_date' => $member->membership_end_date?->format('F j, Y'),
            'days_remaining' => $daysUntilExpiry,
        ];

        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Membership Renewal Reminder',
                'emails.membership.renewal-reminder',
                $data
            );
        }

        if ($user->phone && $this->smsService->isAvailable()) {
            $message = "Your membership expires in {$daysUntilExpiry} days ({$data['expiry_date']}). Please renew to maintain your benefits.";
            $this->smsService->send($user->phone, $message);
        }
    }

    /**
     * Send registration confirmation notification.
     */
    public function sendRegistrationConfirmation(TrainingRegistration $registration): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        if ($user->email) {
            $result = $this->emailService->sendTemplate(
                $user->email,
                "Registration Confirmation - {$package->name}",
                'emails.training.registration-confirmation',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'registrationDate' => $registration->registration_date->format('F j, Y'),
                    'trainingSchedule' => $this->formatSchedule($package),
                    'feeAmount' => $package->getFormattedFee(),
                ]
            );

            if (!$result['success']) {
                Log::warning('Failed to send registration confirmation email', [
                    'registration_id' => $registration->id,
                    'error' => $result['error'] ?? $result['message'],
                ]);
            }
        }

        if ($user->phone) {
            $message = $this->smsService->sendTemplate(
                $user->phone,
                "Training Registration: You have been registered for {training}. Date: {date}",
                [
                    'training' => $package->name,
                    'date' => $registration->registration_date->format('M d, Y'),
                ]
            );

            if (!$message['success']) {
                Log::warning('Failed to send registration confirmation SMS', [
                    'registration_id' => $registration->id,
                    'error' => $message['error'] ?? $message['message'],
                ]);
            }
        }
    }

    /**
     * Send approval notification.
     */
    public function sendApprovalNotification(TrainingRegistration $registration): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        if ($user->email) {
            $this->emailService->sendTemplate(
                $user->email,
                "Registration Approved - {$package->name}",
                'emails.training.approval',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'schedule' => $this->formatSchedule($package),
                ]
            );
        }

        if ($user->phone) {
            $this->smsService->sendTemplate(
                $user->phone,
                "Your registration for {training} has been approved!",
                [
                    'training' => $package->name,
                ]
            );
        }
    }

    /**
     * Send rejection notification.
     */
    public function sendRejectionNotification(TrainingRegistration $registration, string $reason): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        if ($user->email) {
            $this->emailService->sendTemplate(
                $user->email,
                "Registration Update - {$package->name}",
                'emails.training.rejection',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'reason' => $reason,
                ]
            );
        }

        if ($user->phone) {
            $this->smsService->sendTemplate(
                $user->phone,
                "Your registration for {training} was not approved. Reason: {reason}",
                [
                    'training' => $package->name,
                    'reason' => $reason,
                ]
            );
        }
    }

    /**
     * Send training payment failure notification (email + SMS).
     *
     * Requirements: 7.4, 7.5
     */
    public function sendTrainingPaymentFailed(TrainingRegistration $registration, string $reason = ''): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        if (!$user) {
            return;
        }

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Payment Failed – {$package->name}",
                    'emails.training.payment-failed',
                    [
                        'userName'      => $user->name,
                        'trainingName'  => $package->name,
                        'amount'        => $package->getFormattedFee(),
                        'reference'     => $registration->payment_reference,
                        'reason'        => $reason ?: 'Payment was not completed.',
                        'supportEmail'  => config('mail.from.address'),
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Payment failed for {training}. Amount: {amount}. Ref: {ref}. Please contact support or retry.",
                    [
                        'training' => $package->name,
                        'amount'   => $package->getFormattedFee(),
                        'ref'      => $registration->payment_reference ?? 'N/A',
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send training payment failure notification', [
                'registration_id' => $registration->id,
                'error'           => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send payment confirmation notification.
     */
    public function sendPaymentConfirmation(TrainingRegistration $registration): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        if ($user->email) {
            $this->emailService->sendTemplate(
                $user->email,
                "Payment Confirmed - {$package->name}",
                'emails.training.payment-confirmation',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'amount' => $package->getFormattedFee(),
                    'transactionId' => $registration->payment_reference,
                ]
            );
        }

        if ($user->phone) {
            $this->smsService->sendTemplate(
                $user->phone,
                "Payment confirmed for {training}. Amount: {amount}. Ref: {ref}",
                [
                    'training' => $package->name,
                    'amount' => $package->getFormattedFee(),
                    'ref' => $registration->payment_reference,
                ]
            );
        }
    }

    /**
     * Send enrollment confirmation with session details.
     */
    public function sendEnrollmentConfirmation(TrainingRegistration $registration): void
    {
        $user = $registration->user;
        $package = $registration->trainingPackage;

        $upcomingSessions = $package->getUpcomingSessions();

        if ($user->email) {
            $this->emailService->sendTemplate(
                $user->email,
                "Enrollment Confirmed - {$package->name}",
                'emails.training.enrollment-confirmation',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'schedule' => $this->formatSchedule($package),
                    'sessions' => $upcomingSessions->map(function ($session) {
                        return [
                            'name' => $session->session_name,
                            'date' => $session->getFormattedDate(),
                            'time' => $session->getFormattedTimeRange(),
                            'venue' => $session->venue_name ?: 'Online',
                            'meeting_link' => $session->meeting_link,
                        ];
                    }),
                ]
            );
        }

        if ($user->phone && $upcomingSessions->isNotEmpty()) {
            $firstSession = $upcomingSessions->first();
            $this->smsService->sendTemplate(
                $user->phone,
     
                "Enrollment confirmed for {training}. First session: {date} at {time}. Venue: {venue}",
                [
                    'training' => $package->name,
                    'date' => $firstSession->getFormattedDate(),
                    'time' => $firstSession->getFormattedTimeRange(),
                    'venue' => $firstSession->venue_name ?: 'Online',
                ]
            );
        }
    }

    /**
     * Send schedule change notification.
     */
    public function sendScheduleChangeNotification(TrainingSession $session): void
    {
        $package = $session->trainingPackage;

        $registrations = $package->registrations()
            ->where('status', 'approved')
            ->with('user')
            ->get();

        foreach ($registrations as $registration) {
            $user = $registration->user;

            if ($user->email) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Schedule Update - {$package->name}",
                    'emails.training.schedule-change',
                    [
                        'userName' => $user->name,
                        'trainingName' => $package->name,
                        'sessionName' => $session->session_name,
                        'newDate' => $session->getFormattedDate(),
                        'newTime' => $session->getFormattedTimeRange(),
                    ]
                );
            }

            if ($user->phone) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Training schedule update: {session} for {training} has been rescheduled to {date} at {time}",
                    [
                        'session' => $session->session_name,
                        'training' => $package->name,
                        'date' => $session->getFormattedDate(),
                        'time' => $session->getFormattedTimeRange(),
                    ]
                );
            }
        }
    }

    /**
     * Send cancellation notification.
     */
    public function sendCancellationNotification(TrainingSession $session, string $reason): void
    {
        $package = $session->trainingPackage;

        $registrations = $package->registrations()
            ->where('status', 'approved')
            ->with('user')
            ->get();

        foreach ($registrations as $registration) {
            $user = $registration->user;

            if ($user->email) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Session Cancelled - {$package->name}",
                    'emails.training.session-cancelled',
                    [
                        'userName' => $user->name,
                        'trainingName' => $package->name,
                        'sessionName' => $session->session_name,
                        'reason' => $reason,
                    ]
                );
            }

            if ($user->phone) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Training session cancelled: {session} for {training}. Reason: {reason}",
                    [
                        'session' => $session->session_name,
                        'training' => $package->name,
                        'reason' => $reason,
                    ]
                );
            }
        }
    }

    /**
     * Send certificate issued notification.
     */
    public function sendCertificateIssuedNotification(TrainingCertificate $certificate): void
    {
        $user = $certificate->user;
        $package = $certificate->trainingPackage;

        if ($user->email) {
            $this->emailService->sendTemplate(
                $user->email,
                "Certificate Issued - {$package->name}",
                'emails.training.certificate-issued',
                [
                    'userName' => $user->name,
                    'trainingName' => $package->name,
                    'certificateNumber' => $certificate->certificate_number,
                    'issueDate' => $certificate->getFormattedIssueDate(),
                    'verificationUrl' => route('public.certificates.verify', $certificate->verification_code),
                ]
            );
        }

        if ($user->phone) {
            $this->smsService->sendTemplate(
                $user->phone,
                "Certificate issued for {training}! Certificate No: {number}. Verify at {url}",
                [
                    'training' => $package->name,
                    'number' => $certificate->certificate_number,
                    'url' => route('public.certificates.verify', $certificate->verification_code),
                ]
            );
        }
    }

    /**
     * Send training reminder.
     */
    public function sendTrainingReminder(TrainingSession $session): void
    {
        $package = $session->trainingPackage;

        $registrations = $package->registrations()
            ->where('status', 'approved')
            ->with('user')
            ->get();

        foreach ($registrations as $registration) {
            $user = $registration->user;

            if ($user->email) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Training Reminder - {$session->session_name}",
                    'emails.training.reminder',
                    [
                        'userName' => $user->name,
                        'trainingName' => $package->name,
                        'sessionName' => $session->session_name,
                        'date' => $session->getFormattedDate(),
                        'time' => $session->getFormattedTimeRange(),
                        'venue' => $session->venue_name ?: 'Online',
                        'meetingLink' => $session->meeting_link,
                    ]
                );
            }

            if ($user->phone) {
                $venue = $session->venue_name ?: ($session->meeting_link ? 'Online' : 'TBA');
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Reminder: {session} tomorrow at {time}. Venue: {venue}",
                    [
                        'session' => $session->session_name,
                        'time' => $session->getFormattedTimeRange(),
                        'venue' => $venue,
                    ]
                );
            }
        }
    }

    /**
     * Send contribution payment failure notification (email + SMS).
     *
     * Requirements: 8.4, 8.5
     */
    public function sendContributionPaymentFailed(Contribution $contribution, string $reason = ''): void
    {
        $member = $contribution->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    'Contribution Payment Failed',
                    'emails.contributions.payment-failed',
                    [
                        'name'    => $user->name,
                        'amount'  => $contribution->formatted_amount,
                        'period'  => $contribution->period,
                        'reference' => $contribution->reference_number,
                        'reason'  => $reason ?: 'Payment was not completed.',
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Payment failed for contribution {period}. Amount: {amount}. Ref: {ref}. Please retry.",
                    [
                        'period' => $contribution->period,
                        'amount' => $contribution->formatted_amount,
                        'ref'    => $contribution->reference_number,
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send contribution payment failure notification', [
                'contribution_id' => $contribution->id,
                'error'           => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send self-paced payment receipt after successful enrollment payment.
     */
    public function sendSelfPacedPaymentReceipt(Enrollment $enrollment): void
    {
        $user = $enrollment->user;
        $course = $enrollment->course;

        if (!$user) {
            return;
        }

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Payment Receipt – {$course->title}",
                    'emails.self-paced.payment-receipt',
                    [
                        'enrollment' => $enrollment,
                        'course'     => $course,
                        'user'       => $user,
                        'portalUrl'  => route('self-paced.learn.my-courses'),
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Payment confirmed for {course}. Amount: {amount}. Ref: {ref}. Access your course at " . route('self-paced.learn.my-courses'),
                    [
                        'course' => $course->title,
                        'amount' => number_format((float) $enrollment->amount_paid, 2) . ' ' . ($course->currency ?? config('services.mtn_momo.currency', 'SSP')),
                        'ref'    => $enrollment->payment_reference,
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send self-paced payment receipt', [
                'enrollment_id' => $enrollment->id,
                'error'         => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send self-paced payment failure notification.
     */
    public function sendSelfPacedPaymentFailed(Enrollment $enrollment): void
    {
        $user = $enrollment->user;
        $course = $enrollment->course;

        if (!$user) {
            return;
        }

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    "Payment Failed – {$course->title}",
                    'emails.self-paced.payment-failed',
                    [
                        'enrollment' => $enrollment,
                        'course'     => $course,
                        'user'       => $user,
                        'retryUrl'   => route('self-paced.public.payment', [$course->slug, $enrollment->id]),
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Payment failed for {course}. Amount: {amount}. Ref: {ref}. Please retry your payment.",
                    [
                        'course' => $course->title,
                        'amount' => number_format((float) $enrollment->amount_paid, 2) . ' ' . ($course->currency ?? config('services.mtn_momo.currency', 'SSP')),
                        'ref'    => $enrollment->payment_reference,
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send self-paced payment failure notification', [
                'enrollment_id' => $enrollment->id,
                'error'         => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send loan repayment failure notification (email + SMS).
     *
     * Requirements: 9.5
     */
    public function sendLoanRepaymentFailed(LoanRepayment $repayment, string $reason = ''): void
    {
        $application = $repayment->loanApplication;
        $member = $application->member;
        $user = $member?->user;

        if (!$user) {
            return;
        }

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    'Loan Repayment Failed',
                    'emails.loans.repayment-failed',
                    [
                        'name'               => $user->name,
                        'amount'             => number_format($repayment->scheduled_amount, 2),
                        'currency'           => $application->currency,
                        'reference'          => $repayment->reference_number,
                        'installment'        => $repayment->installment_number,
                        'total_installments' => $application->term_months,
                        'reason'             => $reason ?: 'Payment was not completed.',
                        'support_email'      => config('mail.from.address'),
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Loan repayment failed. Amount: {currency} {amount}. Ref: {ref}. Please retry or contact support.",
                    [
                        'currency' => $application->currency,
                        'amount'   => number_format($repayment->scheduled_amount, 2),
                        'ref'      => $repayment->reference_number,
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send loan repayment failure notification', [
                'repayment_id' => $repayment->id,
                'error'        => $e->getMessage(),
            ]);
        }
    }

    /**
     * Send Health Directory payment failure notification (email + SMS).
     *
     * Requirements: 10.4, 10.5
     */
    public function sendHealthDirectoryPaymentFailed($payment, string $listingType = 'listing', string $reason = ''): void
    {
        $user = $payment->user;

        if (!$user) {
            return;
        }

        $entity = $payment->institution ?? $payment->machine ?? null;
        $entityName = $entity?->name ?? ucfirst($listingType) . ' listing';

        try {
            if ($this->emailService->isReady()) {
                $this->emailService->sendTemplate(
                    $user->email,
                    'Health Directory Payment Failed',
                    'emails.health-directory.payment-failed',
                    [
                        'name'         => $user->name,
                        'listing_type' => ucfirst($listingType),
                        'entity_name'  => $entityName,
                        'amount'       => $payment->formatted_amount,
                        'reference'    => $payment->reference,
                        'reason'       => $reason ?: 'Payment was not completed.',
                        'support_email' => config('mail.from.address'),
                    ]
                );
            }

            if ($user->phone && $this->smsService->isAvailable()) {
                $this->smsService->sendTemplate(
                    $user->phone,
                    "Payment failed for {type} listing ({name}). Amount: {amount}. Ref: {ref}. Please retry.",
                    [
                        'type'   => ucfirst($listingType),
                        'name'   => $entityName,
                        'amount' => $payment->formatted_amount,
                        'ref'    => $payment->reference,
                    ]
                );
            }
        } catch (\Throwable $e) {
            Log::error('Failed to send health directory payment failure notification', [
                'payment_id' => $payment->id,
                'error'      => $e->getMessage(),
            ]);
        }
    }

    /**
     * Format schedule for notifications.
     */
    protected function formatSchedule($package): string
    {
        $sessions = $package->getUpcomingSessions();

        if ($sessions->isEmpty()) {
            return 'Schedule to be announced';
        }

        return $sessions->map(function ($session) {
            return $session->getFormattedDate() . ' at ' . $session->getFormattedTimeRange();
        })->join(', ');
    }
}
