<?php

namespace App\Services;

use App\Models\Notification;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Pagination\LengthAwarePaginator;

class NotificationService
{
    /**
     * Create a new notification
     */
    public function createNotification(array $data): Notification
    {
        return Notification::create([
            'user_id' => $data['user_id'],
            'type' => $data['type'],
            'title' => $data['title'],
            'body' => $data['body'],
            'data' => $data['data'] ?? null,
        ]);
    }

    /**
     * Create notification for new listing
     */
    public function createNewListingNotification(User $user, array $propertyData): Notification
    {
        return $this->createNotification([
            'user_id' => $user->id,
            'type' => Notification::TYPE_NEW_LISTING,
            'title' => 'New Property Available',
            'body' => "A new property '{$propertyData['title']}' is now available in your area",
            'data' => [
                'property_id' => $propertyData['id'],
                'property_title' => $propertyData['title'],
                'property_type' => $propertyData['property_type'],
                'monthly_rent' => $propertyData['monthly_rent'],
            ],
        ]);
    }

    /**
     * Create notification for booking request
     */
    public function createBookingRequestNotification(User $user, array $bookingData): Notification
    {
        return $this->createNotification([
            'user_id' => $user->id,
            'type' => Notification::TYPE_BOOKING_REQUEST,
            'title' => 'New Booking Request',
            'body' => "You have a new booking request for '{$bookingData['property_title']}'",
            'data' => [
                'booking_id' => $bookingData['id'],
                'property_id' => $bookingData['property_id'],
                'property_title' => $bookingData['property_title'],
                'tenant_name' => $bookingData['tenant_name'],
                'start_date' => $bookingData['start_date'],
                'end_date' => $bookingData['end_date'],
            ],
        ]);
    }

    /**
     * Create notification for payment reminder
     */
    public function createPaymentReminderNotification(User $user, array $paymentData): Notification
    {
        return $this->createNotification([
            'user_id' => $user->id,
            'type' => Notification::TYPE_PAYMENT_REMINDER,
            'title' => 'Payment Reminder',
            'body' => "Payment reminder for '{$paymentData['property_title']}' - Amount: {$paymentData['amount']}",
            'data' => [
                'payment_id' => $paymentData['id'],
                'property_id' => $paymentData['property_id'],
                'property_title' => $paymentData['property_title'],
                'amount' => $paymentData['amount'],
                'due_date' => $paymentData['due_date'],
            ],
        ]);
    }

    /**
     * Get user notifications
     */
    public function getUserNotifications(int $userId, array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = Notification::where('user_id', $userId)
            ->orderBy('created_at', 'desc');

        if (isset($filters['type'])) {
            $query->byType($filters['type']);
        }

        if (isset($filters['unread_only']) && $filters['unread_only']) {
            $query->where('is_read', false);
        }

        if (isset($filters['recent_days'])) {
            $query->recent($filters['recent_days']);
        }

        return $query->paginate($perPage);
    }

    /**
     * Get unread notifications count
     */
    public function getUnreadCount(int $userId): int
    {
        return Notification::unread($userId)->count();
    }

    /**
     * Mark notification as read
     */
    public function markAsRead(int $notificationId, int $userId): bool
    {
        return Notification::where('id', $notificationId)
            ->where('user_id', $userId)
            ->update(['is_read' => true]) > 0;
    }

    /**
     * Mark all notifications as read for user
     */
    public function markAllAsRead(int $userId): int
    {
        return Notification::where('user_id', $userId)
            ->where('is_read', false)
            ->update(['is_read' => true]);
    }

    /**
     * Delete notification
     */
    public function deleteNotification(int $notificationId, int $userId): bool
    {
        return Notification::where('id', $notificationId)
            ->where('user_id', $userId)
            ->delete() > 0;
    }

    /**
     * Get notification statistics
     */
    public function getNotificationStatistics(int $userId): array
    {
        $total = Notification::where('user_id', $userId)->count();
        $unread = $this->getUnreadCount($userId);

        $byType = Notification::where('user_id', $userId)
            ->selectRaw('type, COUNT(*) as count')
            ->groupBy('type')
            ->pluck('count', 'type')
            ->toArray();

        return [
            'total' => $total,
            'unread' => $unread,
            'by_type' => [
                'new_listing' => $byType[Notification::TYPE_NEW_LISTING] ?? 0,
                'booking_request' => $byType[Notification::TYPE_BOOKING_REQUEST] ?? 0,
                'payment_reminder' => $byType[Notification::TYPE_PAYMENT_REMINDER] ?? 0,
                'message' => $byType[Notification::TYPE_MESSAGE] ?? 0,
            ],
        ];
    }

    /**
     * Bulk create notifications for multiple users
     */
    public function createBulkNotifications(array $userIds, array $notificationData): int
    {
        $notifications = [];
        $now = now();

        foreach ($userIds as $userId) {
            $notifications[] = [
                'user_id' => $userId,
                'type' => $notificationData['type'],
                'title' => $notificationData['title'],
                'body' => $notificationData['body'],
                'data' => $notificationData['data'] ?? null,
                'created_at' => $now,
                'updated_at' => $now,
            ];
        }

        return Notification::insert($notifications);
    }

    /**
     * Format notification for API response
     */
    public function formatNotificationForResponse(Notification $notification): array
    {
        return [
            'id' => $notification->id,
            'type' => $notification->type,
            'type_name' => $notification->type_name,
            'title' => $notification->title,
            'body' => $notification->body,
            'data' => $notification->data,
            'is_read' => $notification->is_read,
            'created_at' => $notification->created_at,
        ];
    }

    /**
     * Format notifications for API response
     */
    public function formatNotificationsForResponse(Collection $notifications): array
    {
        return $notifications->map(function ($notification) {
            return $this->formatNotificationForResponse($notification);
        })->toArray();
    }
}
