<?php

namespace App\Http\Controllers\CheckIn;

use App\Http\Controllers\Controller;
use App\Models\CheckinDevice;
use App\Models\Event;
use App\Models\EventGuest;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;

class CheckInEventController extends Controller
{
    public function validate(Request $request): JsonResponse
    {
        $request->validate([
            'event_code'  => 'required|string|max:20',
            'device_name' => 'nullable|string|max:100',
        ]);

        $code  = strtoupper(trim($request->event_code));

        try {
            $event = Event::where('code', $code)->where('is_active', true)->first();
        } catch (\Exception $e) {
            return response()->json(['error' => 'Database error (events): ' . $e->getMessage()], 500);
        }

        if (! $event) {
            return response()->json(['error' => 'Invalid or inactive event code.'], 422);
        }

        $deviceToken = Str::random(48);
        $expiresAt   = now()->addHours(12);

        try {
            CheckinDevice::create([
                'device_token' => $deviceToken,
                'device_name'  => $request->device_name ?? 'Unknown Device',
                'event_id'     => $event->id,
                'event_code'   => $event->code,
                'expires_at'   => $expiresAt,
                'last_seen_at' => now(),
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => 'Database error (checkin_devices): ' . $e->getMessage()], 500);
        }

        return response()->json([
            'device_token' => $deviceToken,
            'expires_at'   => $expiresAt->toIso8601String(),
            'event' => [
                'id'         => $event->id,
                'code'       => $event->code,
                'name'       => $event->name,
                'venue'      => $event->venue ?? $event->location ?? null,
                'event_date' => $event->event_date?->format('Y-m-d'),
                'event_date_formatted' => $event->event_date?->format('M d, Y'),
            ],
        ]);
    }

    public function download(Request $request): JsonResponse
    {
        $eventId  = $request->attributes->get('active_event_id');
        // Card images live on the FurahaCards server. FURAHACARDS_URL points there
        // so the PWA can display them without needing its own copy.
        $cardBase = rtrim(env('FURAHACARDS_URL', config('app.url')), '/') . '/storage/';

        $guests = EventGuest::where('event_id', $eventId)
            ->select([
                'id', 'event_id', 'name', 'phone', 'card_number', 'card_type',
                'total_attendees', 'checked_in_count', 'checked_in_at',
                'first_checkin_at', 'second_checkin_at',
                'third_checkin_at', 'fourth_checkin_at',
                'companion_names', 'generated_card_url', 'rsvp_status',
            ])
            ->get()
            ->map(function ($guest) use ($cardBase) {
                // Convert relative path (e.g. "cards/guest-1-123.png") to a full URL
                if ($guest->generated_card_url && !str_starts_with($guest->generated_card_url, 'http')) {
                    $guest->generated_card_url = $cardBase . $guest->generated_card_url;
                }
                return $guest;
            });

        return response()->json([
            'guests'        => $guests,
            'total'         => $guests->count(),
            'downloaded_at' => now()->toIso8601String(),
        ]);
    }

    public function stats(Request $request): JsonResponse
    {
        $eventId = $request->attributes->get('active_event_id');

        $row = EventGuest::where('event_id', $eventId)
            ->selectRaw('
                COUNT(*) as total_guests,
                COALESCE(SUM(total_attendees), 0) as total_attendees,
                COALESCE(SUM(checked_in_count), 0) as total_checked_in,
                SUM(CASE WHEN COALESCE(checked_in_count,0) > 0 THEN 1 ELSE 0 END) as cards_checked_in
            ')
            ->first();

        // Order by most-recent check-in across all attendees on the card.
        // last_check_in_at is updated on every check-in; checked_in_at is only
        // set on the first, so using COALESCE keeps multi-attendee cards current.
        $recent = EventGuest::where('event_id', $eventId)
            ->whereNotNull('checked_in_at')
            ->orderByRaw('COALESCE(last_check_in_at, checked_in_at) DESC')
            ->limit(10)
            ->get(['id', 'name', 'card_type', 'checked_in_count', 'total_attendees', 'checked_in_at', 'last_check_in_at']);

        return response()->json([
            'stats'  => $row,
            'recent' => $recent,
            'as_of'  => now()->toIso8601String(),
        ]);
    }

    public function health(): JsonResponse
    {
        $checks = [];
        $ok = true;

        // DB connection
        try {
            DB::select('SELECT 1');
            $checks['db_connection'] = 'ok';
        } catch (\Exception $e) {
            $checks['db_connection'] = 'FAIL: ' . $e->getMessage();
            $ok = false;
        }

        // Required tables
        foreach (['events', 'event_guests', 'checkin_devices'] as $table) {
            try {
                $exists = Schema::hasTable($table);
                $checks['table_' . $table] = $exists ? 'ok' : 'MISSING';
                if (! $exists) $ok = false;
            } catch (\Exception $e) {
                $checks['table_' . $table] = 'FAIL: ' . $e->getMessage();
                $ok = false;
            }
        }

        // Required columns on event_guests
        foreach (['checked_in_count', 'checked_in_at', 'last_check_in_at'] as $col) {
            try {
                $exists = Schema::hasColumn('event_guests', $col);
                $checks['col_event_guests_' . $col] = $exists ? 'ok' : 'MISSING';
                if (! $exists) $ok = false;
            } catch (\Exception $e) {
                $checks['col_event_guests_' . $col] = 'FAIL: ' . $e->getMessage();
                $ok = false;
            }
        }

        return response()->json([
            'status' => $ok ? 'ok' : 'degraded',
            'time'   => now()->toIso8601String(),
            'checks' => $checks,
        ], $ok ? 200 : 500);
    }
}
