<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\InAppNotification;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * In-app уведомления для bell-icon в UI (schema v8.10 §18.5).
 *
 * Все endpoint'ы под `auth:sanctum` (Sanctum SPA mode) — уведомления
 * USER-personal, читать/писать может только сам user.
 *
 * RLS: внутри транзакции `SET LOCAL app.current_tenant_id` = tenant_id user'а.
 * Защита от кражи чужого id: явный `where('user_id', $authUser->id)` поверх RLS.
 */
class InAppNotificationController extends Controller
{
    /**
     * GET /api/notifications?unread_only=1&limit=50.
     *
     * Возвращает: {items, unread_count, total}.
     * Лимит: 1..100 (default 50). Сортировка: created_at DESC.
     */
    public function index(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'unread_only' => 'nullable|in:0,1,true,false',
            'limit' => 'nullable|integer|min:1|max:100',
        ]);

        /** @var User $user */
        $user = $request->user();
        $unreadOnly = filter_var($validated['unread_only'] ?? false, FILTER_VALIDATE_BOOLEAN);
        $limit = (int) ($validated['limit'] ?? 50);

        return DB::transaction(function () use ($user, $unreadOnly, $limit): JsonResponse {
            DB::statement('SET LOCAL app.current_tenant_id = '.(int) $user->tenant_id);

            $query = InAppNotification::query()
                ->where('user_id', $user->id)
                ->orderByDesc('created_at')
                ->orderByDesc('id');

            if ($unreadOnly) {
                $query->whereNull('read_at');
            }

            $items = $query->limit($limit)->get();

            $unreadCount = (int) InAppNotification::query()
                ->where('user_id', $user->id)
                ->whereNull('read_at')
                ->count();

            $total = (int) InAppNotification::query()
                ->where('user_id', $user->id)
                ->count();

            return response()->json([
                'items' => $items->map(fn (InAppNotification $n) => [
                    'id' => $n->id,
                    'event' => $n->event,
                    'title' => $n->title,
                    'body' => $n->body,
                    'deal_id' => $n->deal_id,
                    'payload' => $n->payload,
                    'read_at' => $n->read_at?->toIso8601String(),
                    'created_at' => $n->created_at?->toIso8601String(),
                ])->all(),
                'unread_count' => $unreadCount,
                'total' => $total,
            ]);
        });
    }

    /**
     * PATCH /api/notifications/{id}/read.
     *
     * Идемпотентно: повторный вызов не меняет read_at (already-read NO-OP).
     * 404 если notification не принадлежит user'у.
     */
    public function markRead(Request $request, int $id): JsonResponse
    {
        /** @var User $user */
        $user = $request->user();

        return DB::transaction(function () use ($user, $id): JsonResponse {
            DB::statement('SET LOCAL app.current_tenant_id = '.(int) $user->tenant_id);

            $notif = InAppNotification::query()
                ->where('id', $id)
                ->where('user_id', $user->id)
                ->first();

            if ($notif === null) {
                return response()->json(['message' => 'Уведомление не найдено.'], 404);
            }

            if ($notif->read_at === null) {
                $notif->update(['read_at' => now()]);
            }

            return response()->json([
                'id' => $notif->id,
                'read_at' => $notif->read_at?->toIso8601String(),
            ]);
        });
    }

    /**
     * POST /api/notifications/mark-all-read — массовое чтение.
     *
     * Bulk-update read_at=NOW() для всех непрочитанных user'а.
     * Возвращает количество обновлённых.
     */
    public function markAllRead(Request $request): JsonResponse
    {
        /** @var User $user */
        $user = $request->user();

        return DB::transaction(function () use ($user): JsonResponse {
            DB::statement('SET LOCAL app.current_tenant_id = '.(int) $user->tenant_id);

            $updated = InAppNotification::query()
                ->where('user_id', $user->id)
                ->whereNull('read_at')
                ->update(['read_at' => now()]);

            return response()->json([
                'updated' => $updated,
            ]);
        });
    }

    /**
     * DELETE /api/notifications/{id} — удаление одного уведомления.
     *
     * Hard-delete (нет soft-delete для in-app — уведомления накапливаются
     * быстро, ретеншн 90 дней через cleanup-job).
     */
    public function destroy(Request $request, int $id): JsonResponse
    {
        /** @var User $user */
        $user = $request->user();

        return DB::transaction(function () use ($user, $id): JsonResponse {
            DB::statement('SET LOCAL app.current_tenant_id = '.(int) $user->tenant_id);

            $deleted = InAppNotification::query()
                ->where('id', $id)
                ->where('user_id', $user->id)
                ->delete();

            if ($deleted === 0) {
                return response()->json(['message' => 'Уведомление не найдено.'], 404);
            }

            return response()->json(['message' => 'Удалено.']);
        });
    }
}
