<?php

namespace App\Services\BadgeScan;

use App\Models\Configuration;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
 * legacy {@see \App\Controllers\View\RFIDController} parity (badge scan + log listing).
 */
class BadgeScanService
{
    private const LOG_LIMIT = 500;

    /**
     * @return array{recognized: bool, message: string, user_id?: int, display_name?: string}
     */
    public function processScan(string $badgeScan, ?string $schoolYear = null, ?string $semester = null): array
    {
        $tag = trim($badgeScan);
        if ($tag === '') {
            return [
                'recognized' => false,
                'message' => 'Badge scan value is required.',
            ];
        }

        if (! Schema::hasTable('scan_log')) {
            return [
                'recognized' => false,
                'message' => 'Scan logging is not available.',
            ];
        }

        $user = User::query()->where('rfid_tag', $tag)->first();
        if (! $user) {
            return [
                'recognized' => false,
                'message' => 'Badge scan not recognized.',
            ];
        }

        $displayName = trim(($user->firstname ?? '').' '.($user->lastname ?? ''));
        if ($displayName === '') {
            $displayName = $user->email ?? ('User #'.$user->id);
        }

        DB::table('scan_log')->insert([
            'user_id' => $user->id,
            'card_id' => $tag,
            'scan_time' => now(),
            'school_year' => $schoolYear ?: Configuration::getConfigValueByKey('school_year'),
            'semester' => $semester ?: Configuration::getConfigValueByKey('semester'),
        ]);

        return [
            'recognized' => true,
            'message' => 'Badge recognized: '.$displayName,
            'user_id' => (int) $user->id,
            'display_name' => $displayName,
        ];
    }

    /**
     * Scan log listing (legacy RFIDController::log() query shape).
     *
     * @return list<array<string, mixed>>
     */
    public function scanLogRows(?string $schoolYear = null, ?string $semester = null): array
    {
        if (! Schema::hasTable('scan_log')) {
            return [];
        }

        $query = DB::table('scan_log')
            ->select([
                'scan_log.id',
                'scan_log.user_id',
                'scan_log.card_id',
                'scan_log.scan_time',
                'scan_log.school_year',
                'scan_log.semester',
                'users.firstname as user_firstname',
                'users.lastname as user_lastname',
                'students.firstname as student_firstname',
                'students.lastname as student_lastname',
            ])
            ->leftJoin('users', 'users.id', '=', 'scan_log.user_id')
            ->leftJoin('students', 'students.rfid_tag', '=', 'scan_log.card_id');

        if ($schoolYear !== null && trim($schoolYear) !== '') {
            $query->where('scan_log.school_year', trim($schoolYear));
        }

        if ($semester !== null && trim($semester) !== '') {
            $query->where('scan_log.semester', trim($semester));
        }

        return $query
            ->orderByDesc('scan_log.scan_time')
            ->limit(self::LOG_LIMIT)
            ->get()
            ->map(function ($row) {
                $r = (array) $row;
                foreach (['scan_time'] as $k) {
                    if (isset($r[$k]) && $r[$k] !== null && ! is_string($r[$k])) {
                        $r[$k] = (string) $r[$k];
                    }
                }

                return $r;
            })
            ->all();
    }
}
