<?php

declare(strict_types=1);

namespace App\Services;

use App\Contracts\Services\NotificationServiceInterface;
use App\Mail\Bookings\BookingCancelledMail;
use App\Mail\Bookings\BookingConfirmedMail;
use App\Mail\Bookings\BookingDeclinedMail;
use App\Mail\Bookings\BookingRequestedMail;
use App\Mail\Bookings\CheckInReminderMail;
use App\Mail\Reviews\ReviewPostedMail;
use App\Mail\Reviews\ReviewRequestMail;
use App\Models\Booking;
use App\Models\Review;
use App\Models\Transaction;
use App\Notifications\Bookings\BookingCancelledNotification;
use App\Notifications\Bookings\BookingConfirmedNotification;
use App\Notifications\Bookings\BookingDeclinedNotification;
use App\Notifications\Bookings\BookingRequestedNotification;
use App\Notifications\Payments\DisputeResolved;
use App\Notifications\Payments\PaymentDisputed;
use App\Notifications\Payments\PaymentProofSubmitted;
use App\Notifications\Payments\PaymentRefunded;
use App\Notifications\Payments\PaymentRejected;
use App\Notifications\Payments\PaymentVerified;
use App\Notifications\Reviews\ReviewPostedNotification;
use Illuminate\Support\Facades\Mail;

final class NotificationService implements NotificationServiceInterface
{
    /**
     * Send booking requested notification
     */
    public function bookingRequested(Booking $booking): void
    {
        // Notify guest
        $booking->guest->notify(new BookingRequestedNotification($booking, 'guest'));
        Mail::to($booking->guest->email)->send(new BookingRequestedMail($booking, 'guest'));

        // Notify owner
        $booking->property->owner->notify(new BookingRequestedNotification($booking, 'owner'));
        Mail::to($booking->property->owner->email)->send(new BookingRequestedMail($booking, 'owner'));
    }

    /**
     * Send booking confirmed notification
     */
    public function bookingConfirmed(Booking $booking): void
    {
        // Notify guest only
        $booking->guest->notify(new BookingConfirmedNotification($booking));
        Mail::to($booking->guest->email)->send(new BookingConfirmedMail($booking));
    }

    /**
     * Send booking declined notification
     */
    public function bookingDeclined(Booking $booking): void
    {
        // Notify guest only
        $booking->guest->notify(new BookingDeclinedNotification($booking));
        Mail::to($booking->guest->email)->send(new BookingDeclinedMail($booking));
    }

    /**
     * Send booking cancelled notification
     */
    public function bookingCancelled(Booking $booking): void
    {
        // Notify guest
        $booking->guest->notify(new BookingCancelledNotification($booking, 'guest'));
        Mail::to($booking->guest->email)->send(new BookingCancelledMail($booking, 'guest'));

        // Notify owner
        $booking->property->owner->notify(new BookingCancelledNotification($booking, 'owner'));
        Mail::to($booking->property->owner->email)->send(new BookingCancelledMail($booking, 'owner'));
    }

    /**
     * Send check-in reminder notification
     */
    public function checkInReminder(Booking $booking): void
    {
        // Email only (no in-app notification for reminders)
        Mail::to($booking->guest->email)->send(new CheckInReminderMail($booking));
    }

    /**
     * Send review request notification
     */
    public function reviewRequest(Booking $booking): void
    {
        // Email only (no in-app notification for review requests)
        Mail::to($booking->guest->email)->send(new ReviewRequestMail($booking));
    }

    /**
     * Send review posted notification
     */
    public function reviewPosted(Review $review): void
    {
        // Notify owner only
        $review->property->owner->notify(new ReviewPostedNotification($review));
        Mail::to($review->property->owner->email)->send(new ReviewPostedMail($review));
    }

    /**
     * Send payment proof submitted notification
     */
    public function paymentProofSubmitted(Transaction $transaction): void
    {
        // Notify owner that guest uploaded proof
        $transaction->owner->notify(new PaymentProofSubmitted($transaction));

        // Optionally notify admin if configured
        if (config('payment.notifications.notify_admin_on_submission') && config('payment.notifications.admin_email')) {
            // Admin gets email only
            // Mail::to(config('payment.notifications.admin_email'))->send(new PaymentProofSubmittedMail($transaction));
        }
    }

    /**
     * Send payment verified notification
     */
    public function paymentVerified(Transaction $transaction): void
    {
        // Notify guest that payment was verified
        $transaction->user->notify(new PaymentVerified($transaction));
    }

    /**
     * Send payment rejected notification
     */
    public function paymentRejected(Transaction $transaction): void
    {
        // Notify guest that payment was rejected
        $transaction->user->notify(new PaymentRejected($transaction));
    }

    /**
     * Send payment disputed notification
     */
    public function paymentDisputed(Transaction $transaction): void
    {
        // Notify the opposing party
        if ($transaction->disputed_by === $transaction->user_id) {
            // Guest disputed, notify owner
            $transaction->owner->notify(new PaymentDisputed($transaction, 'owner'));
        } else {
            // Owner disputed, notify guest
            $transaction->user->notify(new PaymentDisputed($transaction, 'guest'));
        }

        // Always notify admin about disputes
        if (config('payment.notifications.admin_email')) {
            // Admin gets email notification
            // Mail::to(config('payment.notifications.admin_email'))->send(new PaymentDisputedMail($transaction));
        }
    }

    /**
     * Send dispute resolved notification
     */
    public function disputeResolved(Transaction $transaction): void
    {
        // Notify both guest and owner
        $transaction->user->notify(new DisputeResolved($transaction, 'guest'));
        $transaction->owner->notify(new DisputeResolved($transaction, 'owner'));
    }

    /**
     * Send payment refunded notification
     */
    public function paymentRefunded(Transaction $transaction): void
    {
        // Notify guest about refund
        $transaction->user->notify(new PaymentRefunded($transaction));
    }
}
