<?php

namespace App\Http\Controllers;

use App\Http\Requests\StoreAttendanceEnrollmentRequest;
use App\Models\AttendanceDevice;
use App\Models\AttendanceEnrollment;
use App\Models\PermanentEmployee;
use App\Models\TemporaryEmployee;
use App\Support\StaffAttendance;
use App\Support\StaffType;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class AttendanceEnrollmentController extends Controller
{
    private const PER_PAGE_OPTIONS = [10, 25, 50];

    public function index(Request $request): Response
    {
        $perPage = $request->integer('per_page', 10);
        if (! in_array($perPage, self::PER_PAGE_OPTIONS, true)) {
            $perPage = 10;
        }

        $search = $request->string('search')->trim()->toString();
        $deviceId = $request->integer('device_id');

        $enrollments = AttendanceEnrollment::query()
            ->with('device:id,name,serial_number')
            ->when($deviceId > 0, fn ($q) => $q->where('attendance_device_id', $deviceId))
            ->when($search !== '', function ($query) use ($search): void {
                $query->where(function ($q) use ($search): void {
                    $q->where('device_user_id', 'like', '%'.$search.'%');

                    if (ctype_digit($search)) {
                        $q->orWhere('staff_id', (int) $search);
                    }
                });
            })
            ->orderByDesc('id')
            ->paginate($perPage)
            ->withQueryString();

        $staffKeys = $enrollments->getCollection()->map(fn (AttendanceEnrollment $row): array => [
            'staff_type' => $row->staff_type,
            'staff_id' => $row->staff_id,
        ]);

        $directory = StaffAttendance::staffDirectory($staffKeys);

        $enrollments->through(function (AttendanceEnrollment $row) use ($directory): array {
            $staff = $directory[StaffAttendance::staffKey($row->staff_type, $row->staff_id)] ?? null;

            return [
                'id' => $row->id,
                'attendance_device_id' => $row->attendance_device_id,
                'device_name' => $row->device?->name,
                'device_serial' => $row->device?->serial_number,
                'staff_type' => $row->staff_type,
                'staff_id' => $row->staff_id,
                'staff_name' => $staff['staff_name'] ?? __('Unknown'),
                'national_card_number' => $staff['national_card_number'] ?? null,
                'device_user_id' => $row->device_user_id,
            ];
        });

        return Inertia::render('employees/attendance/enrollments/index', [
            'enrollments' => $enrollments,
            'filters' => [
                'search' => $search,
                'device_id' => $deviceId > 0 ? $deviceId : '',
                'per_page' => $perPage,
            ],
            'devices' => AttendanceDevice::query()
                ->where('is_active', true)
                ->orderBy('name')
                ->get(['id', 'name', 'serial_number']),
            'staffOptions' => $this->staffOptions(),
        ]);
    }

    public function store(StoreAttendanceEnrollmentRequest $request): RedirectResponse
    {
        $validated = $request->validated();

        $validated['device_user_id'] = (string) $validated['staff_id'];

        AttendanceEnrollment::query()->create($validated);

        return redirect()
            ->route('employees.attendance.enrollments.index', $request->only(['search', 'device_id', 'per_page']))
            ->with('status', __('Staff enrolled on device.'));
    }

    public function destroy(Request $request, AttendanceEnrollment $attendanceEnrollment): RedirectResponse
    {
        $attendanceEnrollment->delete();

        return redirect()
            ->route('employees.attendance.enrollments.index', $request->only(['search', 'device_id', 'per_page']))
            ->with('status', __('Device enrollment removed.'));
    }

    /**
     * @return list<array{staff_type: string, staff_id: int, label: string}>
     */
    private function staffOptions(): array
    {
        $options = [];

        foreach (PermanentEmployee::query()
            ->orderBy('full_name')
            ->get(['id', 'full_name', 'national_card_number']) as $employee) {
            $options[] = [
                'staff_type' => StaffType::PERMANENT,
                'staff_id' => $employee->id,
                'label' => $employee->full_name.' — '.$employee->national_card_number,
            ];
        }

        foreach (TemporaryEmployee::query()
            ->orderBy('full_name')
            ->get(['id', 'full_name', 'national_card_number']) as $employee) {
            $options[] = [
                'staff_type' => StaffType::TEMPORARY,
                'staff_id' => $employee->id,
                'label' => $employee->full_name.' — '.$employee->national_card_number,
            ];
        }

        return $options;
    }
}
