<?php

namespace App\Http\Controllers\Controllers;

use Illuminate\Http\Request;
use App\Events\QrTokenIssued;
use App\Services\DynamicQrService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use App\Models\Attendance;
use App\Models\AttendanceSetting;
use App\Models\User;
use Carbon\Carbon;

class AttendanceController extends Controller
{
    private function qrTtl(): int
    {
        return 30;
    }

    private function defaultSettingAttributes(): array
    {
        return [
            'checkin_start' => '07:00:00',
            'checkin_end' => '09:00:00',
            'checkout_start' => '15:00:00',
            'late_grace_minutes' => 0,
            'effective_workdays' => [1, 2, 3, 4, 5],
            'timezone' => 'Asia/Jakarta',
            'allow_checkin_after_end' => true,
            'require_checkout' => true,
            'office_latitude' => -7.5992153,
            'office_longitude' => 112.1035051,
            'attendance_radius_meters' => 90,
        ];
    }

    private function firstSettingOrDefault(): AttendanceSetting
    {
        return AttendanceSetting::query()->first()
            ?? new AttendanceSetting($this->defaultSettingAttributes());
    }

    // Tampilkan page QR
    public function showPage(Request $req, int $sessionId)
    {
        $employees = User::where('status', 'aktif')
            ->with(['attendances' => function ($query) {
                $query->today();
            }])
            ->get()
            ->map(function ($user) {
                $todayAttendance = $user->todayAttendance();

                $checkIn  = ($todayAttendance && $todayAttendance->check_in)
                    ? Carbon::parse($todayAttendance->check_in)->format('h:i A')
                    : '-';

                $checkOut = ($todayAttendance && $todayAttendance->check_out)
                    ? Carbon::parse($todayAttendance->check_out)->format('h:i A')
                    : '-';

                return [
                    'id'       => $user->id,
                    'name'     => $user->name,
                    'role'     => $user->role,
                    'phone'    => $user->phone,
                    'date'     => Carbon::today()->format('d F Y'),
                    'checkin'  => $checkIn,
                    'checkout' => $checkOut,   // baru
                    'status'   => $todayAttendance ? $todayAttendance->status : 'Belum Absen',
                ];
            });

        return view('qrcode.qr-page', [
            'sessionId' => $sessionId,
            'members'   => $employees,
        ]);
    }


    public function currentToken(Request $req, int $sessionId, DynamicQrService $svc)
    {
        $ttl = $this->qrTtl();
        $lead = 2;

        $cacheKey = "qr:session:$sessionId:aktif";
        $data = Cache::get($cacheKey);

        $shouldRotate = true;
        if ($data && isset($data['payload']['exp'])) {
            $remain = (int)($data['payload']['exp'] - now()->timestamp);
            $shouldRotate = $remain <= $lead; // rotate lebih awal
        }

        if ($shouldRotate) {
            $data = $this->generateNewToken($svc, $sessionId, $ttl);
        }

        return response()->json([
            'token' => $data['token'] ?? null,
            'exp'   => $data['payload']['exp'] ?? (now()->addSeconds($ttl)->timestamp),
            'ttl'   => $ttl,
        ]);
    }

    private function generateNewToken(\App\Services\DynamicQrService $svc, int $sessionId, int $ttl): array
    {
        $data = $svc->issueShortToken($sessionId, $ttl);
        Cache::put("qr:session:$sessionId:aktif", $data, $ttl);

        try {
            broadcast(new QrTokenIssued(
                $sessionId,
                $data['token'],
                $data['payload']['exp'],
                $ttl
            ));
        } catch (\Throwable $e) {
            Log::warning('QR broadcast failed (generateNewToken): ' . $e->getMessage(), [
                'session_id' => $sessionId,
            ]);
        }

        return $data;
    }

    // Method untuk force rotate token (bisa dipanggil dari scheduler atau manual)
    public function forceRotate(Request $req, int $sessionId, DynamicQrService $svc)
    {
        $ttl = $this->qrTtl();
        $data = $this->generateNewToken($svc, $sessionId, $ttl);

        return response()->json([
            'ok' => true,
            'message' => 'Token rotated successfully',
            'token' => $data['token'],
            'exp' => $data['payload']['exp'],
            'ttl' => $ttl
        ]);
    }

    public function show()
    {
        $setting = $this->firstSettingOrDefault();

        return view('admin.features.attendance.setting-attendance', compact('setting'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'checkin_start' => ['required', 'date_format:H:i'],
            'checkin_end' => ['required', 'date_format:H:i', 'after:checkin_start'],
            'checkout_start' => ['required', 'date_format:H:i', 'after:checkin_start'],
            'late_grace_minutes' => ['required', 'integer', 'min:0', 'max:1440'],
            'effective_workdays' => ['nullable', 'array'],
            'effective_workdays.*' => ['integer', 'between:1,7'],
            'office_latitude' => ['required', 'numeric', 'between:-90,90'],
            'office_longitude' => ['required', 'numeric', 'between:-180,180'],
            'attendance_radius_meters' => ['required', 'integer', 'min:10', 'max:5000'],
        ]);

        $workdays = collect($validated['effective_workdays'] ?? [])
            ->map(fn($day) => (int) $day)
            ->unique()
            ->sort()
            ->values()
            ->all();

        $setting = AttendanceSetting::query()->first();
        $payload = [
            'checkin_start' => $validated['checkin_start'],
            'checkin_end' => $validated['checkin_end'],
            'checkout_start' => $validated['checkout_start'],
            'late_grace_minutes' => $validated['late_grace_minutes'],
            'effective_workdays' => empty($workdays) ? null : $workdays,
            'timezone' => $setting?->timezone ?? $this->defaultSettingAttributes()['timezone'],
            'allow_checkin_after_end' => $request->boolean('allow_checkin_after_end'),
            'require_checkout' => $request->boolean('require_checkout'),
            'office_latitude' => round((float) $validated['office_latitude'], 7),
            'office_longitude' => round((float) $validated['office_longitude'], 7),
            'attendance_radius_meters' => (int) $validated['attendance_radius_meters'],
        ];

        if ($setting) {
            $setting->update($payload);
        } else {
            AttendanceSetting::create($payload);
        }

        return redirect()
            ->route('admin.attendance.setting.show')
            ->with('success', 'Pengaturan absensi berhasil disimpan.');
    }

    public function updateAttendance(Request $request, Attendance $attendance)
    {
        $validator = Validator::make($request->all(), [
            'status' => ['required', 'in:hadir,izin,sakit,alpha'],
            'notes' => ['required', 'string', 'max:1000'],
            'month' => ['nullable', 'integer', 'between:1,12'],
            'year' => ['nullable', 'integer', 'between:2000,2100'],
        ], [
            'status.required' => 'Status absensi wajib dipilih.',
            'status.in' => 'Status absensi tidak valid.',
            'notes.required' => 'Catatan wajib diisi.',
            'notes.string' => 'Catatan harus berupa teks.',
            'notes.max' => 'Catatan maksimal 1000 karakter.',
            'month.integer' => 'Bulan tidak valid.',
            'month.between' => 'Bulan harus antara 1 sampai 12.',
            'year.integer' => 'Tahun tidak valid.',
            'year.between' => 'Tahun harus antara 2000 sampai 2100.',
        ]);

        if ($validator->fails()) {
            return redirect()
                ->back()
                ->withErrors($validator)
                ->withInput();
        }

        $validated = $validator->validated();

        $notes = trim($validated['notes']);

        if ($notes === '') {
            return redirect()
                ->back()
                ->withErrors(['notes' => 'Catatan wajib diisi.'])
                ->withInput()
                ->with('error', 'Form absensi belum lengkap atau ada data yang tidak valid.');
        }

        $attendance->update([
            'status' => $validated['status'],
            'notes' => $notes,
        ]);

        return redirect()
            ->route('admin.laporan.detail', [
                'user' => $attendance->user_id,
                'month' => $validated['month'] ?? null,
                'year' => $validated['year'] ?? null,
            ])
            ->with('success', 'Data absensi berhasil diperbarui.');
    }

    public function members($sessionId, Request $request)
    {
        // Kalau mau, di sini kamu bisa validasi sessionId benar2 ada.

        $today = Carbon::today();

        // Eager load absensi hari ini (ambil yang terbaru per user)
        $users = User::query()
            ->where('status', 'aktif')
            ->with(['attendances' => function ($q) use ($today) {
                // SESUAIKAN kolom tanggal di tabel absensi:
                // pakai salah satu yang kamu punya: 'date' / 'attendance_date' / 'created_at'
                $q->whereDate('date', $today)      // <-- ganti 'date' jika berbeda
                    ->latest('id');
            }])
            ->select('id', 'name', 'role', 'phone', 'employee_id')
            ->get();

        $rows = $users->map(function ($u) {
            $a = $u->attendances->first(); // hasil eager load di atas (bisa null)
            return [
                'id'          => $u->id,
                'name'        => $u->name,
                'role'        => $u->role,
                'phone'       => $u->phone,
                'employee_id' => $u->employee_id,
                'check_in'    => $a?->check_in,
                'check_out'   => $a?->check_out,
                'status'      => $a?->status,          // 'hadir' | 'izin' | 'sakit' | 'alpha' | null
            ];
        })->values();

        return response()->json($rows);
    }
}
