<?php

namespace App\Http\Controllers\CheckIn;

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

class CheckInSyncController extends Controller
{
    public function sync(Request $request): JsonResponse
    {
        $request->validate([
            'items'               => 'required|array|max:50',
            'items.*.local_id'    => 'required|string|max:64',
            'items.*.guest_id'    => 'required|integer',
            'items.*.method'      => 'required|in:qr_scan,manual_search,manual_entry',
            'items.*.client_time' => 'required|date',
        ]);

        $eventId     = $request->attributes->get('active_event_id');
        $deviceToken = $request->header('X-Device-Token');
        $results     = [];

        foreach ($request->items as $item) {
            // Quick existence check before taking a row lock.
            $exists = EventGuest::where('id', $item['guest_id'])
                ->where('event_id', $eventId)
                ->exists();

            if (! $exists) {
                $results[] = ['local_id' => $item['local_id'], 'status' => 'not_found'];
                continue;
            }

            try {
                $syncResult = DB::transaction(function () use ($item, $eventId, $deviceToken) {
                    // Re-fetch inside the transaction with a row lock so concurrent
                    // syncs from multiple devices cannot double-count check-ins.
                    $guest = EventGuest::where('id', $item['guest_id'])
                        ->where('event_id', $eventId)
                        ->lockForUpdate()
                        ->first();

                    if (! $guest) {
                        return ['status' => 'not_found'];
                    }

                    if ($guest->checked_in_count >= $guest->total_attendees) {
                        return [
                            'status'           => 'already_complete',
                            'checked_in_count' => $guest->checked_in_count,
                            'total_attendees'  => $guest->total_attendees,
                        ];
                    }

                    $count   = $guest->checked_in_count + 1;
                    $tsField = ['first', 'second', 'third', 'fourth'][$count - 1] . '_checkin_at';
                    $ts      = $item['client_time'];

                    $update = [
                        'checked_in_count' => $count,
                        'checked_in_at'    => $guest->checked_in_at ?? $ts,
                        $tsField           => $ts,
                        'check_in_method'  => $item['method'],
                        'scanner_device'   => $deviceToken,
                        'last_check_in_at' => $ts,
                    ];

                    $timestamps   = json_decode($guest->checkin_timestamps ?? '[]', true) ?? [];
                    $timestamps[] = $ts;
                    $update['checkin_timestamps'] = json_encode($timestamps);

                    $guest->update($update);
                    $guest->refresh();

                    return [
                        'status'           => 'synced',
                        'checked_in_count' => $guest->checked_in_count,
                        'total_attendees'  => $guest->total_attendees,
                    ];
                });

                $results[] = array_merge(['local_id' => $item['local_id']], $syncResult);
            } catch (\Throwable $e) {
                $results[] = ['local_id' => $item['local_id'], 'status' => 'error'];
            }
        }

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