<?php

namespace App\Http\Controllers\Api;

use App\Classes\Common;
use App\Classes\CommonHrm;
use App\Http\Controllers\ApiBaseController;
use App\Models\Attendance;
use App\Models\BiometricAttendanceLogs;
use App\Models\BiometricDevice;
use App\Models\Company;
use App\Models\User;
use App\Models\WorkDuration;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class BiometricController extends ApiBaseController
{

    public function connect()
    {
        $request = request();
        $apiToken = $request->get('api_key');
        $biometricDevice = BiometricDevice::where('api_key', $apiToken)->first();

        if (!$biometricDevice) {
            return response()->json(['message' => 'Invalid api key'], 401);
        }

        return response()->json([
            'message' => 'Device found successfully',
            'device'    => $biometricDevice,
        ], 201);
    }

    public function users()
    {
        $request = request();

        // All users which are available in the biometric device
        $users = $request->users;

        $deviceLastSyncDateTime = $request->sync_datetime;

        $companyToken = $request->get('api_key');
        $biometricDevice = BiometricDevice::where('api_key', $companyToken)->first();

        if (!$biometricDevice) {
            return response()->json(['message' => 'Invalid api key'], 401);
        }

        // Updating found_in_biometric in users table
        // based on users received from biometric device
        // reset all to 0
        User::where('company_id', $biometricDevice->company_id)
            ->update(['found_in_biometric' => 0]);

        // set matched ones to 1 (only run when $users not empty)
        if (!empty($users)) {
            User::where('company_id', $biometricDevice->company_id)
                ->whereIn('employee_number', $users)
                ->update(['found_in_biometric' => 1]);
        }

        $modifiedUsers = User::select('name', 'employee_number', 'biometric_card_number')
            ->where('company_id', $biometricDevice->company_id)
            ->where('biometric_user_modified', 1)
            ->get()
            ->map(function ($user) {
                return [
                    'name' => $user->name,
                    'employee_id' => $user->employee_number,
                    'card_number' => $user->biometric_card_number,
                ];
            });

        User::select('name', 'employee_number', 'biometric_card_number')
            ->where('company_id', $biometricDevice->company_id)
            ->where('updated_at', '>=', $deviceLastSyncDateTime)
            ->update([
                'biometric_user_modified' => 0,
            ]);

        $biometricDevice->last_sync_at = $deviceLastSyncDateTime;
        $biometricDevice->save();

        return response()->json([
            'users' => $users,
            'modified_users' => $modifiedUsers,
            'sync_datetime' => Carbon::now()->toDateTimeString(),
        ]);
    }

    public function realTimeLog()
    {
        $request = request();

        Log::info('Biometric real-time log received:');

        $userId = $request->user_id;
        $dateTime = $request->date_time;
        $biometricToken = $request->biometric_token;

        $company = Company::where('biometric_api_key', $biometricToken)->first();

        if (!$company) {
            return response()->json(['message' => 'Invalid company API key'], 401);
        }

        // $dateTime = preg_replace('/ ([-+]\d{2}:\d{2})$/', '+$1', $dateTime);

        $date = Carbon::parse($dateTime)->toDateString();
        $time = Carbon::parse($dateTime)->toTimeString();

        $user = User::where('employee_number', $userId)
            ->where('company_id', $company->id)
            ->first();

        if (!$user) {
            return response()->json(['message' => 'Invalid user or company mismatch'], 404);
        }

        $biometricAttendanceLogs = BiometricAttendanceLogs::create([
            'company_id'       => $company->id,
            'employee_number'  => $user->employee_number,
            'date_time'        => $dateTime,
            'biometric_api_key' => $biometricToken,
        ]);

        $attendance = Attendance::where('user_id', $user->id)
            ->whereDate('date', $date)
            ->first();

        // If no attendance record for the day, create one with clock_in_time as this log time
        $userClockIn = Carbon::createFromFormat('Y-m-d H:i:s', $date . ' ' . $time, $company->timezone);

        if (!$attendance) {
            $attendance = new Attendance();
            $attendance->date          = $date;
            $attendance->user_id       = $user->id;
            $attendance->company_id    = $company->id;
            $attendance->clock_in_time = $time; // set only on first log
            $attendance->clock_in_date_time = $userClockIn->copy()->setTimezone('UTC')->format('Y-m-d H:i:s');
            $attendance->save();

            WorkDuration::create([
                'attendance_id' => $attendance->id,
                'company_id'    => $company->id,
                'start_time'    => $time,
                'status'        => 'started',
                'notes'         => 'Biometric log',
            ]);

            return;
        }

        $lastWork = WorkDuration::where('attendance_id', $attendance->id)
            ->latest('id')
            ->first();

        // If no previous chunk for some reason, treat as first work duration of the day
        if (!$lastWork) {
            WorkDuration::create([
                'attendance_id' => $attendance->id,
                'company_id'    => $company->id,
                'start_time'    => $time,
                'status'        => 'started',
                'notes'         => 'Biometric log',
            ]);
            return;
        }

        // Close the last duration (only if it's still open)
        if (is_null($lastWork->end_time)) {

            $duration = CommonHrm::getMinutesFromTimes($lastWork->start_time, $time);

            $lastWork->update([
                'end_time' => $time,
                'duration' => $duration,
            ]);
        }

        // Toggle status for the next chunk:
        // step 2 → last was "started" → create "paused"
        // step 3 → last was "paused"  → create "started"
        $nextStatus = $lastWork->status === 'started' ? 'paused' : 'started';

        WorkDuration::create([
            'attendance_id' => $attendance->id,
            'company_id'    => $company->id,
            'start_time'    => $time,
            'status'        => $nextStatus,
            'notes'         => 'Biometric log',
        ]);

        return response()->json([
            'message' => 'Log saved successfully',
            'biometricAttendanceLogs'    => $biometricAttendanceLogs,
            'attendance' => $attendance,
        ], 201);
    }
    public function refreshBiometricToken()
    {
        $request = request();
        $company = company();
        // Generate a new token
        $newToken =  Common::generateApiToken();

        // Update the company's biometric API key
        $company->biometric_api_key = $newToken;
        $company->save();

        return response()->json([
            'message' => 'Biometric API key refreshed successfully',
            'value' => $newToken,
        ], 200);
    }
}
