<?php

namespace App\Http\Controllers\Karyawan;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Absensi;
use App\Models\Karyawan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

class AbsensiController extends Controller
{
    public function index()
    {
        $karyawan       = Auth::user()->karyawan;
        $jamKerja       = $karyawan->jamKerja;
        $absensiHariIni = Absensi::where('karyawan_id', $karyawan->id)
                           ->whereDate('tanggal', today())->first();
        $absensiList    = Absensi::where('karyawan_id', $karyawan->id)
                           ->orderByDesc('tanggal')->paginate(20);

        return view('karyawan.absen', compact('karyawan', 'jamKerja', 'absensiHariIni', 'absensiList'));
    }

    public function create()
    {
        $karyawan         = Auth::user()->karyawan;
        $jamKerja         = $karyawan->jamKerja;
        $absensiHariIni   = Absensi::where('karyawan_id', $karyawan->id)
                             ->whereDate('tanggal', today())->first();

        return view('karyawan.absen', compact('karyawan', 'jamKerja', 'absensiHariIni'));
    }

    // ── ABSEN MASUK ───────────────────────────────────────────────────────
    public function absenMasuk(Request $request)
    {
        $karyawan = Auth::user()->karyawan;
        $jamKerja = $karyawan->jamKerja;

        // ── VALIDASI WAKTU (backend) ──────────────────────────────────────
        if ($jamKerja) {
            $jamMasuk       = Carbon::parse($jamKerja->jam_masuk);
            $bolehAbsenDari = $jamMasuk->copy()->subMinutes(30);
            $sekarang       = now();

            if ($sekarang->lt($bolehAbsenDari)) {
                $sisaMenit = $sekarang->diffInMinutes($bolehAbsenDari);
                if ($request->expectsJson()) {
                    return response()->json([
                        'success' => false,
                        'message' => "Absen masuk baru bisa dilakukan mulai pukul {$bolehAbsenDari->format('H:i')} WIB. Tersisa {$sisaMenit} menit lagi."
                    ], 422);
                }
                return back()->with('error', "Absen masuk baru bisa dilakukan mulai pukul {$bolehAbsenDari->format('H:i')} WIB.");
            }
        }

        // ── VALIDASI SUDAH ABSEN ──────────────────────────────────────────
        $sudahAbsen = Absensi::where('karyawan_id', $karyawan->id)
                      ->whereDate('tanggal', today())
                      ->whereNotNull('jam_masuk')->exists();

        if ($sudahAbsen) {
            if ($request->expectsJson()) {
                return response()->json(['success' => false, 'message' => 'Kamu sudah absen masuk hari ini.'], 422);
            }
            return back()->with('error', 'Kamu sudah absen masuk hari ini.');
        }

        $request->validate([
            'latitude'     => 'required|numeric',
            'longitude'    => 'required|numeric',
            'foto_base64'  => 'required|string',
        ]);

        // Simpan foto
        $fotoPath = null;
        if ($request->filled('foto_base64')) {
            $base64  = preg_replace('/^data:image\/\w+;base64,/', '', $request->foto_base64);
            $decoded = base64_decode($base64, true);
            if ($decoded !== false && strlen($decoded) > 0) {
                $filename = 'absensi/masuk/' . uniqid() . '.jpg';
                Storage::disk('public')->put($filename, $decoded);
                $fotoPath = $filename;
            }
        }

        // Hitung status waktu
        $statusWaktu    = 'tepat_waktu';
        $terlambatMenit = 0;

        if ($jamKerja) {
            $jamMasukKerja = Carbon::parse($jamKerja->jam_masuk);
            $batasTerlambat = $jamMasukKerja->copy()->addMinutes($jamKerja->toleransi_menit ?? 0);
            if (now()->gt($batasTerlambat)) {
                $statusWaktu    = 'terlambat';
                $terlambatMenit = (int) now()->diffInMinutes($batasTerlambat);
            }
        }

        // Cek radius GPS
        $instansi     = Auth::user()->instansi;
        $statusMasuk  = 'luar_radius';
        if ($instansi && $instansi->latitude && $instansi->longitude) {
            $dist = $this->haversine(
                $request->latitude, $request->longitude,
                $instansi->latitude, $instansi->longitude
            );
            $statusMasuk = $dist <= ($instansi->radius_meter ?? 100) ? 'dalam_radius' : 'luar_radius';

            // Status luar radius dicatat tapi tidak memblokir absen
            // (GPS PC/browser tidak akurat, validasi radius lebih cocok di HP dengan GPS)
        }

        Absensi::create([
            'karyawan_id'      => $karyawan->id,
            'tanggal'          => today(),
            'jam_masuk'        => now()->format('H:i:s'),
            'foto_masuk'       => $fotoPath,
            'latitude_masuk'   => $request->latitude,
            'longitude_masuk'  => $request->longitude,
            'status_masuk'     => $statusMasuk,
            'status_waktu'     => $statusWaktu,
            'terlambat_menit'  => $terlambatMenit,
        ]);

        if ($request->expectsJson()) {
            return response()->json(['success' => true, 'message' => 'Absen masuk berhasil!']);
        }
        return back()->with('success', 'Absen masuk berhasil dicatat.');
    }

    // ── ABSEN PULANG ──────────────────────────────────────────────────────
    public function absenPulang(Request $request)
    {
        $karyawan = Auth::user()->karyawan;

        $absensi = Absensi::where('karyawan_id', $karyawan->id)
                    ->whereDate('tanggal', today())
                    ->whereNotNull('jam_masuk')
                    ->whereNull('jam_pulang')
                    ->first();

        if (!$absensi) {
            if ($request->expectsJson()) {
                return response()->json(['success' => false, 'message' => 'Tidak ada absen masuk hari ini.'], 422);
            }
            return back()->with('error', 'Tidak ada absen masuk hari ini.');
        }

        // Validasi: tidak boleh absen pulang sebelum jam pulang kerja
        $jamKerja = $karyawan->jamKerja;
        if ($jamKerja) {
            $jamPulangKerja   = Carbon::parse($jamKerja->jam_pulang);
            $bolehPulangDari  = $jamPulangKerja->copy()->subMinutes(15); // boleh 15 menit sebelum jam pulang
            if (now()->lt($bolehPulangDari)) {
                $msg = "Absen pulang baru bisa dilakukan mulai pukul {$bolehPulangDari->format('H:i')} WIB.";
                if ($request->expectsJson()) {
                    return response()->json(['success' => false, 'message' => $msg], 422);
                }
                return back()->with('error', $msg);
            }
        }

        $request->validate([
            'latitude'    => 'required|numeric',
            'longitude'   => 'required|numeric',
            'foto_base64' => 'required|string',
        ]);

        // Simpan foto pulang
        $fotoPath = null;
        if ($request->filled('foto_base64')) {
            $base64  = preg_replace('/^data:image\/\w+;base64,/', '', $request->foto_base64);
            $decoded = base64_decode($base64, true);
            if ($decoded !== false && strlen($decoded) > 0) {
                $filename = 'absensi/pulang/' . uniqid() . '.jpg';
                Storage::disk('public')->put($filename, $decoded);
                $fotoPath = $filename;
            }
        }

        // Cek radius
        $instansi    = Auth::user()->instansi;
        $statusPulang = 'luar_radius';
        if ($instansi && $instansi->latitude && $instansi->longitude) {
            $dist = $this->haversine(
                $request->latitude, $request->longitude,
                $instansi->latitude, $instansi->longitude
            );
            $statusPulang = $dist <= ($instansi->radius_meter ?? 100) ? 'dalam_radius' : 'luar_radius';

            // Status luar radius dicatat tapi tidak memblokir absen pulang
        }

        $absensi->update([
            'jam_pulang'       => now()->format('H:i:s'),
            'foto_pulang'      => $fotoPath,
            'latitude_pulang'  => $request->latitude,
            'longitude_pulang' => $request->longitude,
            'status_pulang'    => $statusPulang,
        ]);

        if ($request->expectsJson()) {
            return response()->json(['success' => true, 'message' => 'Absen pulang berhasil!']);
        }
        return back()->with('success', 'Absen pulang berhasil dicatat. Sampai jumpa besok!');
    }

    public function show($id)
    {
        $karyawan = Auth::user()->karyawan;
        $absensi  = Absensi::where('karyawan_id', $karyawan->id)->findOrFail($id);
        return view('karyawan.absensis.show', compact('absensi'));
    }

    // ── HAVERSINE DISTANCE (meter) ────────────────────────────────────────
    private function haversine($lat1, $lon1, $lat2, $lon2): float
    {
        $R    = 6371000;
        $phi1 = deg2rad($lat1); $phi2 = deg2rad($lat2);
        $dphi = deg2rad($lat2 - $lat1);
        $dlam = deg2rad($lon2 - $lon1);
        $a    = sin($dphi/2)**2 + cos($phi1)*cos($phi2)*sin($dlam/2)**2;
        return $R * 2 * atan2(sqrt($a), sqrt(1 - $a));
    }
}