<?php

namespace App\Http\Controllers\Employee;

use App\Http\Controllers\Controller;
use App\Models\Attendance;
use App\Models\AttendanceSetting;
use App\Models\AuditLog;
use App\Models\OfficeLocation;
use App\Services\AttendanceService;
use App\Services\WhatsAppService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class AttendanceController extends Controller
{
    public function checkInPage()
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();
        $attendance = Attendance::where('employee_id', $employee->id)->whereDate('attendance_date', $today)->first();

        $schedule = $employee->currentSchedule();
        $shift = $schedule?->shift;
        $offices = OfficeLocation::where('is_active', true)->get();

        $requireGps = AttendanceSetting::get('require_gps', 'true') === 'true';
        $requireSelfie = AttendanceSetting::get('require_selfie', 'true') === 'true';

        return view('employee.attendance.check_in', compact(
            'employee',
            'attendance',
            'shift',
            'offices',
            'requireGps',
            'requireSelfie'
        ));
    }

    public function processCheckIn(Request $request, WhatsAppService $whatsAppService)
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();

        // 1. Anti-duplicate validation
        $existing = Attendance::where('employee_id', $employee->id)
            ->whereDate('attendance_date', $today)
            ->first();

        if ($existing && $existing->check_in) {
            return response()->json([
                'success' => false,
                'message' => 'Anda sudah melakukan absensi masuk hari ini pada pukul ' . Carbon::parse($existing->check_in)->format('H:i') . ' WIB.',
            ], 422);
        }

        $validated = $request->validate([
            'latitude' => ['required', 'numeric'],
            'longitude' => ['required', 'numeric'],
            'photo' => ['nullable', 'string'], // base64 encoded photo
            'notes' => ['nullable', 'string'],
        ]);

        $latitude = (float)$validated['latitude'];
        $longitude = (float)$validated['longitude'];

        // 2. GPS Radius & Office Validation
        $nearest = AttendanceService::findNearestOffice($latitude, $longitude);
        $requireGps = AttendanceSetting::get('require_gps', 'true') === 'true';

        if ($requireGps) {
            if (!$nearest || !$nearest['office']) {
                return response()->json([
                    'success' => false,
                    'message' => 'Tidak ada lokasi kantor aktif yang terdaftar dalam sistem.',
                ], 422);
            }

            if (!$nearest['is_within_radius']) {
                return response()->json([
                    'success' => false,
                    'message' => "Anda berada di luar area kantor ({$nearest['office']->name}). Jarak Anda: " . round($nearest['distance']) . " meter (Maksimal: {$nearest['office']->radius_meters} meter).",
                ], 422);
            }
        }

        // 3. Process Selfie Photo (if provided as Base64)
        $photoPath = null;
        if (!empty($validated['photo']) && str_starts_with($validated['photo'], 'data:image')) {
            $imageData = preg_replace('#^data:image/\w+;base64,#i', '', $validated['photo']);
            $decoded = base64_decode($imageData);
            if ($decoded) {
                $filename = 'attendance/in_' . $employee->id . '_' . date('Ymd_His') . '_' . Str::random(6) . '.jpg';
                Storage::disk('public')->put($filename, $decoded);
                $photoPath = 'storage/' . $filename;
            }
        }

        // 4. Determine status & late minutes
        $now = Carbon::now();
        $statusEvaluation = AttendanceService::evaluateCheckInStatus($employee, $now);

        // 5. Save Attendance Record
        $attendance = Attendance::updateOrCreate(
            [
                'employee_id' => $employee->id,
                'attendance_date' => $today,
            ],
            [
                'shift_id' => $statusEvaluation['shift_id'],
                'office_location_id' => $nearest['office']?->id,
                'check_in' => $now->toTimeString(),
                'status' => $statusEvaluation['status'],
                'late_minutes' => $statusEvaluation['late_minutes'],
                'latitude_in' => $latitude,
                'longitude_in' => $longitude,
                'distance_in' => $nearest['distance'] ?? 0,
                'photo_in' => $photoPath,
                'notes' => $validated['notes'] ?? null,
            ]
        );

        AuditLog::log('Absen Masuk', "Karyawan {$employee->name} melakukan absen masuk (Status: {$attendance->status_label}, Jarak: " . round($attendance->distance_in) . "m)");

        // 6. Dispatch WhatsApp Notification
        $whatsAppService->sendAttendanceNotification($employee, 'check_in', [
            'date' => $now->translatedFormat('d F Y'),
            'time' => $now->format('H:i'),
            'status' => $attendance->status_label,
            'distance' => round($attendance->distance_in),
            'late_minutes' => $attendance->late_minutes,
        ]);

        if ($attendance->status === 'late') {
            $whatsAppService->sendAttendanceNotification($employee, 'late', [
                'date' => $now->translatedFormat('d F Y'),
                'time' => $now->format('H:i'),
                'late_minutes' => $attendance->late_minutes,
            ]);
        }

        return response()->json([
            'success' => true,
            'message' => 'Absensi masuk berhasil dicatat!',
            'data' => [
                'status' => $attendance->status_label,
                'check_in' => $now->format('H:i') . ' WIB',
                'late_minutes' => $attendance->late_minutes,
                'distance' => round($attendance->distance_in),
                'office_name' => $nearest['office']?->name ?? 'Kantor',
            ]
        ]);
    }

    public function checkOutPage()
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();
        $attendance = Attendance::where('employee_id', $employee->id)->whereDate('attendance_date', $today)->first();

        $schedule = $employee->currentSchedule();
        $shift = $schedule?->shift;

        return view('employee.attendance.check_out', compact(
            'employee',
            'attendance',
            'shift'
        ));
    }

    public function processCheckOut(Request $request, WhatsAppService $whatsAppService)
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();

        $attendance = Attendance::where('employee_id', $employee->id)
            ->whereDate('attendance_date', $today)
            ->first();

        if (!$attendance || !$attendance->check_in) {
            return response()->json([
                'success' => false,
                'message' => 'Anda belum melakukan absensi masuk hari ini. Silakan absen masuk terlebih dahulu.',
            ], 422);
        }

        if ($attendance->check_out) {
            return response()->json([
                'success' => false,
                'message' => 'Anda sudah melakukan absensi pulang hari ini pada pukul ' . Carbon::parse($attendance->check_out)->format('H:i') . ' WIB.',
            ], 422);
        }

        $validated = $request->validate([
            'latitude' => ['required', 'numeric'],
            'longitude' => ['required', 'numeric'],
            'photo' => ['nullable', 'string'],
        ]);

        $latitude = (float)$validated['latitude'];
        $longitude = (float)$validated['longitude'];

        $nearest = AttendanceService::findNearestOffice($latitude, $longitude);
        $now = Carbon::now();

        // Process Selfie Photo if provided
        $photoPath = null;
        if (!empty($validated['photo']) && str_starts_with($validated['photo'], 'data:image')) {
            $imageData = preg_replace('#^data:image/\w+;base64,#i', '', $validated['photo']);
            $decoded = base64_decode($imageData);
            if ($decoded) {
                $filename = 'attendance/out_' . $employee->id . '_' . date('Ymd_His') . '_' . Str::random(6) . '.jpg';
                Storage::disk('public')->put($filename, $decoded);
                $photoPath = 'storage/' . $filename;
            }
        }

        $attendance->update([
            'check_out' => $now->toTimeString(),
            'latitude_out' => $latitude,
            'longitude_out' => $longitude,
            'distance_out' => $nearest['distance'] ?? 0,
            'photo_out' => $photoPath,
        ]);

        AuditLog::log('Absen Pulang', "Karyawan {$employee->name} melakukan absen pulang");

        $whatsAppService->sendAttendanceNotification($employee, 'check_out', [
            'date' => $now->translatedFormat('d F Y'),
            'time' => $now->format('H:i'),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Absensi pulang berhasil dicatat. Selamat beristirahat!',
            'data' => [
                'check_out' => $now->format('H:i') . ' WIB',
            ]
        ]);
    }

    public function scanQrPage()
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();
        $attendance = Attendance::where('employee_id', $employee->id)->whereDate('attendance_date', $today)->first();

        $schedule = $employee->currentSchedule();
        $shift = $schedule?->shift;
        $offices = OfficeLocation::where('is_active', true)->get();

        $primaryOffice = $offices->first();
        $maxGpsAccuracy = $primaryOffice?->max_gps_accuracy ?? (int)AttendanceSetting::get('max_gps_accuracy', 30);
        $officeRadius = $primaryOffice?->radius_meters ?? (int)AttendanceSetting::get('default_radius_meters', 10);

        return view('employee.attendance.scan_qr', compact(
            'employee',
            'attendance',
            'shift',
            'offices',
            'primaryOffice',
            'maxGpsAccuracy',
            'officeRadius'
        ));
    }

    public function processQrScan(Request $request, WhatsAppService $whatsAppService)
    {
        $employee = Auth::user()->employee;
        $today = Carbon::today()->toDateString();
        $now = Carbon::now();

        $validated = $request->validate([
            'qr_code' => ['required', 'string'],
            'latitude' => ['required', 'numeric', 'between:-90,90'],
            'longitude' => ['required', 'numeric', 'between:-180,180'],
            'accuracy' => ['required', 'numeric', 'min:0'],
        ]);

        $qrCode = trim($validated['qr_code']);
        $latitude = (float)$validated['latitude'];
        $longitude = (float)$validated['longitude'];
        $accuracy = (float)$validated['accuracy'];

        // 0. Validate Employee Status
        if ($employee->status !== 'active') {
            return response()->json([
                'success' => false,
                'message' => 'Status kepegawaian Anda saat ini Nonaktif. Silakan hubungi HR Admin.',
            ], 403);
        }

        // 1. Resolve Office from QR Code payload (Direct URL, ABSENSI-OFFICE-X, or numeric ID)
        $officeId = null;
        if (preg_match('/\/attend\/qr\/(\d+)/', $qrCode, $matches)) {
            $officeId = (int)$matches[1];
        } elseif (preg_match('/ABSENSI-OFFICE-(\d+)/', $qrCode, $matches)) {
            $officeId = (int)$matches[1];
        } elseif (preg_match('/OFFICE-(\d+)/', $qrCode, $matches)) {
            $officeId = (int)$matches[1];
        } elseif (is_numeric($qrCode)) {
            $officeId = (int)$qrCode;
        }

        // 2. Strict Server-Side Location & GPS Accuracy Validation
        $locationValidation = AttendanceService::validateLocationAndAccuracy($latitude, $longitude, $accuracy, $officeId);

        if (!$locationValidation['valid']) {
            return response()->json([
                'success' => false,
                'error_type' => $locationValidation['error_type'],
                'message' => $locationValidation['message'],
                'data' => [
                    'distance' => round($locationValidation['distance'], 1),
                    'accuracy' => round($accuracy, 1),
                    'radius' => $locationValidation['radius'] ?? null,
                ]
            ], 422);
        }

        $office = $locationValidation['office'];
        $distance = $locationValidation['distance'];
        $schedule = $employee->currentSchedule();
        $shift = $schedule?->shift;

        // 3. Determine Check-In vs Check-Out Flow
        $attendance = Attendance::where('employee_id', $employee->id)
            ->whereDate('attendance_date', $today)
            ->first();

        // Flow A: Belum absen masuk -> PROSES CHECK-IN
        if (!$attendance || !$attendance->check_in) {
            $statusEvaluation = AttendanceService::evaluateCheckInStatus($employee, $now);

            $attendance = Attendance::updateOrCreate(
                [
                    'employee_id' => $employee->id,
                    'attendance_date' => $today,
                ],
                [
                    'shift_id' => $statusEvaluation['shift_id'],
                    'office_location_id' => $office->id,
                    'check_in' => $now->toTimeString(),
                    'status' => $statusEvaluation['status'],
                    'late_minutes' => $statusEvaluation['late_minutes'],
                    'latitude_in' => $latitude,
                    'longitude_in' => $longitude,
                    'distance_in' => $distance,
                    'accuracy_in' => $accuracy,
                    'qr_code_scanned' => $qrCode,
                    'notes' => 'Absensi Masuk via QR Scanner',
                ]
            );

            AuditLog::log('QR Check-In', "Karyawan {$employee->name} ({$employee->nik}) berhasil scan QR Masuk (Jarak: " . round($distance, 1) . "m, Akurasi: " . round($accuracy, 1) . "m)");

            // WhatsApp Notification if enabled
            $whatsAppService->sendAttendanceNotification($employee, 'check_in', [
                'date' => $now->translatedFormat('d F Y'),
                'time' => $now->format('H:i'),
                'status' => $attendance->status_label,
                'distance' => round($distance, 1),
                'late_minutes' => $attendance->late_minutes,
            ]);

            return response()->json([
                'success' => true,
                'type' => 'check_in',
                'message' => "Presensi Masuk Berhasil dicatat. Status: {$attendance->status_label}",
                'data' => [
                    'action' => 'check_in',
                    'status' => $attendance->status_label,
                    'status_badge' => $attendance->status === 'late' ? 'bg-warning text-dark' : 'bg-success text-white',
                    'time' => $now->format('H:i:s') . ' WIB',
                    'date' => $now->translatedFormat('l, d F Y'),
                    'distance' => round($distance, 1),
                    'accuracy' => round($accuracy, 1),
                    'office_name' => $office->name,
                    'late_minutes' => $attendance->late_minutes,
                    // Profil Karyawan Terverifikasi
                    'employee' => [
                        'name' => $employee->name,
                        'nik' => $employee->nik,
                        'department' => $employee->department?->name ?? 'Staff',
                        'position' => $employee->position?->name ?? 'Karyawan',
                        'avatar' => $employee->photo ? asset($employee->photo) : null,
                        'shift_name' => $shift ? $shift->name : 'Shift Reguler',
                        'shift_hours' => $shift ? \Carbon\Carbon::parse($shift->start_time)->format('H:i') . ' - ' . \Carbon\Carbon::parse($shift->end_time)->format('H:i') . ' WIB' : '08:00 - 17:00 WIB',
                    ]
                ]
            ]);
        }

        // Flow B: Sudah absen masuk, belum absen pulang -> PROSES CHECK-OUT
        if (!$attendance->check_out) {
            $attendance->update([
                'check_out' => $now->toTimeString(),
                'latitude_out' => $latitude,
                'longitude_out' => $longitude,
                'distance_out' => $distance,
                'accuracy_out' => $accuracy,
                'qr_code_scanned' => $attendance->qr_code_scanned . ' | OUT:' . $qrCode,
                'notes' => ($attendance->notes ? $attendance->notes . ' | ' : '') . 'Check-out via QR Scanner',
            ]);

            AuditLog::log('QR Check-Out', "Karyawan {$employee->name} ({$employee->nik}) berhasil scan QR Pulang (Jarak: " . round($distance, 1) . "m)");

            $whatsAppService->sendAttendanceNotification($employee, 'check_out', [
                'date' => $now->translatedFormat('d F Y'),
                'time' => $now->format('H:i'),
            ]);

            return response()->json([
                'success' => true,
                'type' => 'check_out',
                'message' => "Presensi Pulang Berhasil dicatat. Terima kasih atas dedikasi Anda hari ini.",
                'data' => [
                    'action' => 'check_out',
                    'status' => 'Selesai Bertugas',
                    'status_badge' => 'bg-primary text-white',
                    'time' => $now->format('H:i:s') . ' WIB',
                    'check_in_time' => Carbon::parse($attendance->check_in)->format('H:i') . ' WIB',
                    'date' => $now->translatedFormat('l, d F Y'),
                    'distance' => round($distance, 1),
                    'accuracy' => round($accuracy, 1),
                    'office_name' => $office->name,
                    // Profil Karyawan Terverifikasi
                    'employee' => [
                        'name' => $employee->name,
                        'nik' => $employee->nik,
                        'department' => $employee->department?->name ?? 'Staff',
                        'position' => $employee->position?->name ?? 'Karyawan',
                        'avatar' => $employee->photo ? asset($employee->photo) : null,
                        'shift_name' => $shift ? $shift->name : 'Shift Reguler',
                    ]
                ]
            ]);
        }

        // Flow C: Sudah absen masuk dan pulang hari ini
        return response()->json([
            'success' => false,
            'message' => 'Anda sudah menyelesaikan absensi masuk (' . Carbon::parse($attendance->check_in)->format('H:i') . ' WIB) dan absensi pulang (' . Carbon::parse($attendance->check_out)->format('H:i') . ' WIB) untuk hari ini.',
        ], 422);
    }

    public function history(Request $request)
    {
        $employee = Auth::user()->employee;
        $query = Attendance::where('employee_id', $employee->id);

        if ($request->filled('month') && $request->filled('year')) {
            $query->whereMonth('attendance_date', $request->month)
                ->whereYear('attendance_date', $request->year);
        }

        $attendances = $query->latest('attendance_date')->paginate(15)->withQueryString();

        return view('employee.attendance.history', compact('employee', 'attendances'));
    }
}
