<?php

namespace App\Services;

use App\Models\Appointment;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

class AppointmentNotificationService
{
    /**
     * Send appointment confirmation notification
     */
    public function sendConfirmationNotification(Appointment $appointment): bool
    {
        try {
            // Load relationships if not already loaded
            $appointment->load(['customer', 'vehicle', 'assignedTechnician']);

            // Send email notification
            $this->sendConfirmationEmail($appointment);

            // Log successful notification
            Log::info('Appointment confirmation notification sent', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'scheduled_datetime' => $appointment->scheduled_datetime,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send appointment confirmation notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send appointment reminder notification
     */
    public function sendReminderNotification(Appointment $appointment): bool
    {
        try {
            $appointment->load(['customer', 'vehicle', 'assignedTechnician']);

            // Send email reminder
            $this->sendReminderEmail($appointment);

            Log::info('Appointment reminder notification sent', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'scheduled_datetime' => $appointment->scheduled_datetime,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send appointment reminder notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send appointment cancellation notification
     */
    public function sendCancellationNotification(Appointment $appointment, string $reason = ''): bool
    {
        try {
            $appointment->load(['customer', 'vehicle', 'assignedTechnician']);

            // Send email notification
            $this->sendCancellationEmail($appointment, $reason);

            Log::info('Appointment cancellation notification sent', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'reason' => $reason,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send appointment cancellation notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send appointment reschedule notification
     */
    public function sendRescheduleNotification(Appointment $appointment, Carbon $oldDateTime): bool
    {
        try {
            $appointment->load(['customer', 'vehicle', 'assignedTechnician']);

            // Send email notification
            $this->sendRescheduleEmail($appointment, $oldDateTime);

            Log::info('Appointment reschedule notification sent', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'old_datetime' => $oldDateTime,
                'new_datetime' => $appointment->scheduled_datetime,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send appointment reschedule notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send completed service notification
     */
    public function sendCompletionNotification(Appointment $appointment): bool
    {
        try {
            $appointment->load(['customer', 'vehicle', 'assignedTechnician', 'serviceOrder']);

            // Send email notification
            $this->sendCompletionEmail($appointment);

            Log::info('Service completion notification sent', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'completed_at' => $appointment->completed_at,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send service completion notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send daily appointment reminders
     */
    public function sendDailyReminders(): int
    {
        $tomorrow = now()->addDay();
        $remindersSent = 0;

        // Get appointments scheduled for tomorrow that are confirmed
        $appointments = Appointment::with(['customer', 'vehicle', 'assignedTechnician'])
            ->whereDate('scheduled_datetime', $tomorrow->toDateString())
            ->where('status', 'confirmed')
            ->get();

        foreach ($appointments as $appointment) {
            if ($this->sendReminderNotification($appointment)) {
                $remindersSent++;
            }
        }

        Log::info('Daily appointment reminders sent', [
            'date' => $tomorrow->toDateString(),
            'reminders_sent' => $remindersSent,
            'total_appointments' => $appointments->count(),
        ]);

        return $remindersSent;
    }

    /**
     * Send overdue appointment notifications
     */
    public function sendOverdueNotifications(): int
    {
        $notificationsSent = 0;

        // Get appointments that are overdue (scheduled but past their time)
        $overdueAppointments = Appointment::with(['customer', 'vehicle', 'assignedTechnician'])
            ->where('status', 'scheduled')
            ->where('scheduled_datetime', '<', now()->subMinutes(30)) // 30 minutes past
            ->get();

        foreach ($overdueAppointments as $appointment) {
            // Mark as no-show and send notification
            if ($appointment->markNoShow()) {
                $this->sendNoShowNotification($appointment);
                $notificationsSent++;
            }
        }

        Log::info('Overdue appointment notifications sent', [
            'notifications_sent' => $notificationsSent,
            'overdue_appointments' => $overdueAppointments->count(),
        ]);

        return $notificationsSent;
    }

    /**
     * Send no-show notification
     */
    private function sendNoShowNotification(Appointment $appointment): bool
    {
        try {
            // This would typically send an internal notification to staff
            // and possibly a follow-up email to the customer
            
            Log::info('Customer marked as no-show', [
                'appointment_id' => $appointment->id,
                'customer_id' => $appointment->customer_id,
                'scheduled_datetime' => $appointment->scheduled_datetime,
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to send no-show notification', [
                'appointment_id' => $appointment->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Send confirmation email
     */
    private function sendConfirmationEmail(Appointment $appointment): void
    {
        $data = [
            'appointment' => $appointment,
            'customer' => $appointment->customer,
            'vehicle' => $appointment->vehicle,
            'technician' => $appointment->assignedTechnician,
            'shopName' => config('app.name', 'Auto Repair Shop'),
        ];

        // In a real application, you would create a Mailable class
        // For now, we'll simulate the email sending
        $this->simulateEmail($appointment->customer->email, 'Appointment Confirmation', $data);
    }

    /**
     * Send reminder email
     */
    private function sendReminderEmail(Appointment $appointment): void
    {
        $data = [
            'appointment' => $appointment,
            'customer' => $appointment->customer,
            'vehicle' => $appointment->vehicle,
            'technician' => $appointment->assignedTechnician,
            'shopName' => config('app.name', 'Auto Repair Shop'),
        ];

        $this->simulateEmail($appointment->customer->email, 'Appointment Reminder', $data);
    }

    /**
     * Send cancellation email
     */
    private function sendCancellationEmail(Appointment $appointment, string $reason): void
    {
        $data = [
            'appointment' => $appointment,
            'customer' => $appointment->customer,
            'vehicle' => $appointment->vehicle,
            'reason' => $reason,
            'shopName' => config('app.name', 'Auto Repair Shop'),
        ];

        $this->simulateEmail($appointment->customer->email, 'Appointment Cancelled', $data);
    }

    /**
     * Send reschedule email
     */
    private function sendRescheduleEmail(Appointment $appointment, Carbon $oldDateTime): void
    {
        $data = [
            'appointment' => $appointment,
            'customer' => $appointment->customer,
            'vehicle' => $appointment->vehicle,
            'technician' => $appointment->assignedTechnician,
            'oldDateTime' => $oldDateTime,
            'shopName' => config('app.name', 'Auto Repair Shop'),
        ];

        $this->simulateEmail($appointment->customer->email, 'Appointment Rescheduled', $data);
    }

    /**
     * Send completion email
     */
    private function sendCompletionEmail(Appointment $appointment): void
    {
        $data = [
            'appointment' => $appointment,
            'customer' => $appointment->customer,
            'vehicle' => $appointment->vehicle,
            'technician' => $appointment->assignedTechnician,
            'serviceOrder' => $appointment->serviceOrder,
            'shopName' => config('app.name', 'Auto Repair Shop'),
        ];

        $this->simulateEmail($appointment->customer->email, 'Service Completed', $data);
    }

    /**
     * Simulate email sending (replace with actual Mail::send in production)
     */
    private function simulateEmail(string $email, string $subject, array $data): void
    {
        // In production, replace this with:
        // Mail::send('emails.appointment.template', $data, function ($message) use ($email, $subject) {
        //     $message->to($email)->subject($subject);
        // });

        Log::info('Email notification simulated', [
            'to' => $email,
            'subject' => $subject,
            'appointment_id' => $data['appointment']->id ?? null,
        ]);
    }

    /**
     * Get notification preferences for a customer
     */
    public function getCustomerNotificationPreferences($customerId): array
    {
        // In a real application, this would fetch from customer preferences
        // For now, return default preferences
        return [
            'email_confirmations' => true,
            'email_reminders' => true,
            'email_cancellations' => true,
            'sms_reminders' => false, // Could be implemented later
            'reminder_hours_before' => 24,
        ];
    }

    /**
     * Check if notification should be sent based on customer preferences
     */
    public function shouldSendNotification($customerId, string $notificationType): bool
    {
        $preferences = $this->getCustomerNotificationPreferences($customerId);

        return match($notificationType) {
            'confirmation' => $preferences['email_confirmations'] ?? true,
            'reminder' => $preferences['email_reminders'] ?? true,
            'cancellation' => $preferences['email_cancellations'] ?? true,
            default => true,
        };
    }
}
