<?php

namespace App\Http\Controllers;

use App\Models\ManagementAlert;
use App\Models\ReminderNotificationLog;
use App\Services\BranchAccessService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\View\View;

class NotificationCenterController extends Controller
{
    public function __construct(private BranchAccessService $branchAccess)
    {
    }

    public function index(Request $request): View
    {
        $user = $request->user();
        $status = in_array((string) $request->string('status'), ['all', 'unread', 'read'], true)
            ? (string) $request->string('status')
            : 'all';

        $personalQuery = $user->notifications()->latest();
        if ($status === 'unread') {
            $personalQuery->whereNull('read_at');
        } elseif ($status === 'read') {
            $personalQuery->whereNotNull('read_at');
        }

        $personalCounts = [
            'all' => $user->notifications()->count(),
            'unread' => $user->unreadNotifications()->count(),
            'read' => $user->readNotifications()->count(),
        ];

        $alerts = collect();
        $alertSummary = ['active' => 0, 'critical' => 0];
        if ($user->can('management-alerts.view')) {
            $alertQuery = ManagementAlert::query()
                ->with('branch')
                ->whereIn('status', ['open', 'acknowledged']);
            $this->branchAccess->constrainBranchOwnedQuery($alertQuery, $user);
            $alertSummary = [
                'active' => (clone $alertQuery)->count(),
                'critical' => (clone $alertQuery)->where('severity', 'critical')->count(),
            ];
            $alerts = (clone $alertQuery)
                ->orderByRaw("CASE severity WHEN 'critical' THEN 1 WHEN 'warning' THEN 2 ELSE 3 END")
                ->orderByDesc('occurred_at')
                ->limit(8)
                ->get();
        }

        $deliveryFailures = collect();
        $deliveryFailureCount = 0;
        if ($user->can('notifications.view')) {
            $failureQuery = ReminderNotificationLog::query()
                ->with(['branch', 'customer', 'loan'])
                ->where('status', 'failed');
            $this->branchAccess->constrainBranchOwnedQuery($failureQuery, $user);
            $deliveryFailureCount = (clone $failureQuery)->count();
            $deliveryFailures = (clone $failureQuery)->latest('last_attempt_at')->latest('id')->limit(8)->get();
        }

        return view('notification-center.index', [
            'notifications' => $personalQuery->paginate(20)->withQueryString(),
            'personalCounts' => $personalCounts,
            'status' => $status,
            'alerts' => $alerts,
            'alertSummary' => $alertSummary,
            'deliveryFailures' => $deliveryFailures,
            'deliveryFailureCount' => $deliveryFailureCount,
        ]);
    }

    public function read(Request $request, string $notification): RedirectResponse
    {
        $this->ownedNotification($request, $notification)->markAsRead();

        return back()->with('success', 'Notification marked as read.');
    }

    public function readAll(Request $request): RedirectResponse
    {
        $request->user()->unreadNotifications()->update(['read_at' => now()]);

        return back()->with('success', 'All personal notifications marked as read.');
    }

    public function open(Request $request, string $notification): RedirectResponse
    {
        $item = $this->ownedNotification($request, $notification);
        $item->markAsRead();
        $data = (array) $item->data;

        if (($data['event'] ?? null) === 'management_alert' && $request->user()->can('management-alerts.view')) {
            return redirect()->route('management-alerts.index');
        }

        if (isset($data['loan_id']) && $request->user()->can('loans.view')) {
            return redirect()->route('loans.show', ['loan' => (int) $data['loan_id']]);
        }

        return redirect()->route('notification-center.index');
    }

    public function destroy(Request $request, string $notification): RedirectResponse
    {
        $this->ownedNotification($request, $notification)->delete();

        return back()->with('success', 'Notification removed.');
    }

    private function ownedNotification(Request $request, string $id): DatabaseNotification
    {
        return $request->user()->notifications()->whereKey($id)->firstOrFail();
    }
}
