<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api;

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

/**
 * Reminders API (schema v8.10 §17.5). Все endpoint'ы под `auth:sanctum`.
 *
 * Фильтры filter= для GET /api/reminders:
 *   today      — completed_at IS NULL AND remind_at в (now-1d, now+1d)
 *   upcoming   — completed_at IS NULL AND remind_at > now+1d
 *   overdue    — completed_at IS NULL AND remind_at < now-1d
 *   completed  — completed_at IS NOT NULL
 *   active     — completed_at IS NULL (default)
 *
 * RLS: внутри транзакции SET LOCAL app.current_tenant_id = $user->tenant_id.
 * Защита от кражи: явный where('tenant_id', $user->tenant_id) поверх RLS.
 */
class ReminderController extends Controller
{
    private const FILTERS = ['active', 'today', 'upcoming', 'overdue', 'completed'];

    /**
     * GET /api/reminders?filter=&deal_id=&limit=
     */
    public function index(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'filter' => 'nullable|string|in:'.implode(',', self::FILTERS),
            'deal_id' => 'nullable|integer|min:1',
            'limit' => 'nullable|integer|min:1|max:200',
        ]);

        /** @var User $user */
        $user = $request->user();
        $filter = $validated['filter'] ?? 'active';
        $limit = (int) ($validated['limit'] ?? 100);

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

            $query = Reminder::query()
                ->with('creator:id,email,first_name,last_name')
                ->where('tenant_id', $user->tenant_id);

            if (isset($validated['deal_id'])) {
                $query->where('deal_id', (int) $validated['deal_id']);
            }

            $now = Carbon::now();
            switch ($filter) {
                case 'today':
                    $query->whereNull('completed_at')
                        ->whereBetween('remind_at', [$now->copy()->subDay(), $now->copy()->addDay()]);
                    break;
                case 'upcoming':
                    $query->whereNull('completed_at')
                        ->where('remind_at', '>', $now->copy()->addDay());
                    break;
                case 'overdue':
                    $query->whereNull('completed_at')
                        ->where('remind_at', '<', $now->copy()->subDay());
                    break;
                case 'completed':
                    $query->whereNotNull('completed_at');
                    break;
                case 'active':
                default:
                    $query->whereNull('completed_at');
                    break;
            }

            $items = $query->orderBy('remind_at')->limit($limit)->get();

            // Counters для UI badges (today/upcoming/overdue) — отдельные SELECT'ы.
            $base = Reminder::query()->where('tenant_id', $user->tenant_id);
            $counts = [
                'today' => (clone $base)->whereNull('completed_at')
                    ->whereBetween('remind_at', [$now->copy()->subDay(), $now->copy()->addDay()])
                    ->count(),
                'upcoming' => (clone $base)->whereNull('completed_at')
                    ->where('remind_at', '>', $now->copy()->addDay())
                    ->count(),
                'overdue' => (clone $base)->whereNull('completed_at')
                    ->where('remind_at', '<', $now->copy()->subDay())
                    ->count(),
                'active' => (clone $base)->whereNull('completed_at')->count(),
            ];

            return response()->json([
                'items' => $items->map(fn (Reminder $r) => $this->toResource($r))->all(),
                'counts' => $counts,
            ]);
        });
    }

    /**
     * POST /api/reminders {deal_id, text?, remind_at}.
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'deal_id' => 'required|integer|min:1',
            'text' => 'nullable|string|max:255',
            'remind_at' => 'required|date',
            'assignee_id' => 'nullable|integer|min:1',
        ]);

        /** @var User $user */
        $user = $request->user();

        // Manager FK guard для assignee_id: должен принадлежать тому же tenant'у.
        if (isset($validated['assignee_id'])) {
            $exists = User::query()
                ->where('id', $validated['assignee_id'])
                ->where('tenant_id', $user->tenant_id)
                ->whereNull('deleted_at')
                ->where('is_active', true)
                ->exists();
            if (! $exists) {
                return response()->json([
                    'message' => 'Менеджер не найден в этом тенанте.',
                    'errors' => ['assignee_id' => ['Не принадлежит вашему тенанту или не активен.']],
                ], 422);
            }
        }

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

            $reminder = Reminder::create([
                'tenant_id' => $user->tenant_id,
                'deal_id' => (int) $validated['deal_id'],
                'text' => $validated['text'] ?? null,
                'remind_at' => Carbon::parse($validated['remind_at']),
                'created_by' => $user->id,
                'assignee_id' => $validated['assignee_id'] ?? null,
                'is_sent' => false,
            ]);

            return response()->json([
                'reminder' => $this->toResource($reminder->load('creator:id,email,first_name,last_name')),
            ], 201);
        });
    }

    /**
     * PATCH /api/reminders/{id} {text?, remind_at?, assignee_id?}.
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $validated = $request->validate([
            'text' => 'nullable|string|max:255',
            'remind_at' => 'nullable|date',
            'assignee_id' => 'nullable|integer|min:1',
        ]);

        if (count($validated) === 0) {
            return response()->json([
                'message' => 'Передайте хотя бы одно поле.',
                'errors' => ['_general' => ['Нужно хотя бы одно поле для обновления.']],
            ], 422);
        }

        /** @var User $user */
        $user = $request->user();

        if (isset($validated['assignee_id'])) {
            $exists = User::query()
                ->where('id', $validated['assignee_id'])
                ->where('tenant_id', $user->tenant_id)
                ->whereNull('deleted_at')
                ->where('is_active', true)
                ->exists();
            if (! $exists) {
                return response()->json([
                    'message' => 'Менеджер не найден.',
                    'errors' => ['assignee_id' => ['Не принадлежит вашему тенанту или не активен.']],
                ], 422);
            }
        }

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

            $reminder = Reminder::query()
                ->where('id', $id)
                ->where('tenant_id', $user->tenant_id)
                ->first();

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

            $update = [];
            if (array_key_exists('text', $validated)) {
                $update['text'] = $validated['text'];
            }
            if (isset($validated['remind_at'])) {
                $update['remind_at'] = Carbon::parse($validated['remind_at']);
                // При сдвиге remind_at сбрасываем is_sent, чтобы cron смог
                // снова отправить уведомление к новому времени.
                $update['is_sent'] = false;
                $update['sent_at'] = null;
            }
            if (array_key_exists('assignee_id', $validated)) {
                $update['assignee_id'] = $validated['assignee_id'];
            }

            $reminder->update($update);

            return response()->json([
                'reminder' => $this->toResource($reminder->fresh('creator')),
            ]);
        });
    }

    /**
     * POST /api/reminders/{id}/complete — пометить выполненным.
     * Идемпотентно: повторный вызов NO-OP.
     */
    public function complete(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);

            $reminder = Reminder::query()
                ->where('id', $id)
                ->where('tenant_id', $user->tenant_id)
                ->first();

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

            if ($reminder->completed_at === null) {
                $reminder->update(['completed_at' => Carbon::now()]);
            }

            return response()->json([
                'reminder' => $this->toResource($reminder->fresh('creator')),
            ]);
        });
    }

    /**
     * DELETE /api/reminders/{id}.
     */
    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 = Reminder::query()
                ->where('id', $id)
                ->where('tenant_id', $user->tenant_id)
                ->delete();

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

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

    /** @return array<string, mixed> */
    private function toResource(Reminder $reminder): array
    {
        $creator = $reminder->creator;

        return [
            'id' => $reminder->id,
            'deal_id' => $reminder->deal_id,
            'text' => $reminder->text,
            'remind_at' => $reminder->remind_at?->toIso8601String(),
            'completed_at' => $reminder->completed_at?->toIso8601String(),
            'is_sent' => $reminder->is_sent,
            'sent_at' => $reminder->sent_at?->toIso8601String(),
            'created_at' => $reminder->created_at?->toIso8601String(),
            'created_by' => $reminder->created_by,
            'assignee_id' => $reminder->assignee_id,
            'creator_name' => $creator
                ? trim(($creator->first_name ?? '').' '.($creator->last_name ?? '')) ?: $creator->email
                : null,
        ];
    }
}
