<?php

namespace App\Http\Controllers\SystemSettings;

use App\Events\NotificationSent;
use App\Models\Notification;
use App\Repositories\NotificationRepository;
use App\Services\SystemConfig\SystemConfigService;
use App\Support\DataTable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
use Spatie\Permission\Models\Role;

class NotificationCenterController extends Controller
{
    public function __construct(
        protected SystemConfigService $systemConfig,
        protected NotificationRepository $notificationRepo
    ) {
        // Middleware handled in web.php
    }

    protected function ensureFeatureEnabled(): void
    {
        $featureEnabled = $this->systemConfig->get('feature_notification_center', true);

        if (! $featureEnabled) {
            // Instead of 404, we change the authorization requirement.
            // If feature is disabled, only users who can 'manage global settings' can access.
            abort_unless(
                Auth::user()?->can('manage global settings'),
                403,
                __('The Notification Center feature is currently disabled by the system administrator.')
            );
        }
    }

    /**
     * =====================================================
     * INDEX
     * =====================================================
     */
    public function index(Request $request)
    {
        $this->ensureFeatureEnabled();

        if (DataTable::isDataTableRequest($request)) {
            return $this->dataTable($request);
        }

        $roles = Role::pluck('name')->toArray();

        return view('pages.system_settings.notification-center', compact('roles'));
    }

    /**
     * DATATABLE (Supports personal status)
     */
    protected function dataTable(Request $request)
    {
        try {
            $user = Auth::user();
            $authorizedRecipients = $this->notificationRepo->getAuthorizedRecipients($user);

            $start = DataTable::start($request);
            $length = DataTable::length($request);

            // Efficient query using LEFT JOIN (no N+1)
            $baseQuery = Notification::whereIn('recipient', $authorizedRecipients)
                ->leftJoin('system_notification_user', function ($join) use ($user) {
                    $join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
                        ->where('system_notification_user.user_id', '=', $user->id);
                })
                ->whereNull('system_notification_user.deleted_at')
                ->select('system_notifications.*', 'system_notification_user.read_at as personal_read_at');

            $recordsTotal = $baseQuery->count();
            $recordsFiltered = $recordsTotal;

            $notifications = (clone $baseQuery)
                ->latest('system_notifications.created_at')
                ->skip($start)
                ->take($length)
                ->get();

            $rows = $notifications->map(function ($n) {
                return [
                    'id' => $n->id,
                    'is_unread' => is_null($n->personal_read_at),
                    'title' => e($n->title),
                    'message' => e(strip_tags($n->message)),
                    'type' => $n->type,
                    'recipient' => $n->recipient,
                    'time_ago' => $n->created_at ? $n->created_at->diffForHumans() : '',
                    'read_url' => route('notification-center.read', $n->id),
                    'delete_url' => route('notification-center.destroy', $n->id),
                    'created_at' => $n->created_at ? $n->created_at->format('Y-m-d H:i:s') : '',
                ];
            })->values();

            return DataTable::response($request, $recordsTotal, $recordsFiltered, $rows->toArray());
        } catch (\Exception $e) {
            \Log::error('NotificationCenter DataTable Error: '.$e->getMessage());

            return response()->json(['error' => $e->getMessage(), 'data' => []], 500);
        }
    }

    /**
     * STORE (Send Broadcast)
     */
    public function store(Request $request)
    {
        $this->ensureFeatureEnabled();

        $roles = Role::pluck('name')->toArray();
        $roles[] = 'all';

        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'message' => 'required|string',
            'recipient' => 'required|in:'.implode(',', $roles),
            'type' => 'required|in:info,warning,system',
        ]);

        $notification = $this->notificationRepo->create([
            ...$validated,
            'created_by' => Auth::id(),
            'read_at' => null,
        ]);

        event(new NotificationSent($notification));

        return response()->json(['success' => true, 'message' => __('Notification broadcasted.')]);
    }

    /**
     * MARK AS READ (Personal)
     */
    public function markAsRead(Notification $notification)
    {
        $this->ensureFeatureEnabled();
        $this->notificationRepo->markAsRead($notification->id, Auth::id());

        return response()->json(['success' => true, 'message' => __('Marked as read.')]);
    }

    /**
     * DELETE (Personal Hide)
     */
    public function destroy(Notification $notification)
    {
        $this->ensureFeatureEnabled();
        $this->notificationRepo->personalDelete($notification->id, Auth::id());

        return response()->json(['success' => true, 'message' => __('Notification hidden.')]);
    }

    /**
     * MARK ALL AS READ (Personal)
     */
    public function markAllAsRead()
    {
        $this->ensureFeatureEnabled();
        $this->notificationRepo->markAllAsReadForUser(Auth::user());

        return response()->json(['success' => true, 'message' => __('All marked as read.')]);
    }

    /**
     * CLEAR READ (Personal Hide all read)
     */
    public function clearRead()
    {
        $this->ensureFeatureEnabled();
        $user = Auth::user();

        $readIds = \DB::table('system_notification_user')
            ->where('user_id', $user->id)
            ->whereNotNull('read_at')
            ->pluck('notification_id');

        foreach ($readIds as $id) {
            $this->notificationRepo->personalDelete($id, $user->id);
        }

        return response()->json(['success' => true, 'message' => __('Read notifications cleared from your view.')]);
    }

    /**
     * RECENT NOTIFICATIONS API (Personal status)
     */
    public function recentNotifications(Request $request)
    {
        $this->ensureFeatureEnabled();
        $user = Auth::user();
        $offset = $request->get('offset', 0);
        $limit = $request->get('limit', 10);

        $notifications = $this->notificationRepo->getActiveNotificationsForUser($user, $offset, $limit);

        $mapped = $notifications->map(function ($n) {
            return [
                'id' => $n->id,
                'title' => e($n->title),
                'message' => e(strip_tags($n->message)),
                'type' => $n->type,
                'time_ago' => $n->created_at->diffForHumans(),
                'read_url' => route('notification-center.read', $n->id),
                'delete_url' => route('notification-center.destroy', $n->id),
                'is_unread' => is_null($n->personal_read_at),
                'recipient' => $n->recipient,
            ];
        })->values()->all();

        return response()->json([
            'success' => true,
            'unread_count' => $this->notificationRepo->getUnreadCount($user),
            'notifications' => $mapped,
            'has_more' => count($mapped) === (int) $limit,
        ]);
    }
}
