<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Models\AbsensiModel;
use App\Models\GuruModel;
use App\Models\SiswaModel;
use App\Models\SettingGpsModel;
use App\Models\SettingJamModel;
use App\Models\SettingWhatsappModel;
use App\Models\KegiatanSholatModel;
use App\Models\KegiatanEkskulModel;
use App\Models\AbsensiKegiatanModel;
use CodeIgniter\API\ResponseTrait;

class Absensi extends BaseController
{
    use ResponseTrait;

    public function scanPage()
    {
        if (! session()->get('logged_in')) {
            return redirect()->to('/');
        }
        
        $sholatModel = new KegiatanSholatModel();
        $ekskulModel = new KegiatanEkskulModel();
        
        $hariInggris = date('l');
        $map = [
            'Sunday' => 'Minggu', 'Monday' => 'Senin', 'Tuesday' => 'Selasa',
            'Wednesday' => 'Rabu', 'Thursday' => 'Kamis', 'Friday' => 'Jumat', 'Saturday' => 'Sabtu'
        ];
        $hariIni = $map[$hariInggris];

        $listSholat = $sholatModel->findAll();
        $listEkskul = $ekskulModel->where('hari', $hariIni)->findAll();

        $data = [
            'title' => 'Scan QR Code',
            'list_sholat' => $listSholat,
            'list_ekskul' => $listEkskul
        ];
        return view('absensi/scan', $data);
    }

    public function processScan()
    {
        date_default_timezone_set('Asia/Jakarta');

        if (!$this->request->isAJAX()) {
            return $this->failForbidden('Akses ditolak');
        }

        $qrContent = $this->request->getPost('qr_content');
        $userLat   = $this->request->getPost('latitude');
        $userLong  = $this->request->getPost('longitude');
        $jenisAbsen = $this->request->getPost('jenis_absen');

        if (empty($qrContent) || empty($userLat) || empty($userLong)) {
            return $this->fail('Data tidak lengkap. Pastikan GPS aktif dan QR terbaca.');
        }

        $gpsModel = new SettingGpsModel();
        $settingGps = $gpsModel->first();

        if (!$settingGps) {
            return $this->fail('Pengaturan Lokasi Sekolah belum diset oleh Admin.');
        }

        $jarak = $this->calculateDistance($userLat, $userLong, $settingGps['latitude'], $settingGps['longitude']);

        if ($jarak > $settingGps['radius_meter']) {
            return $this->fail("Lokasi Anda terlalu jauh. Jarak: " . round($jarak) . "m. Batas: " . $settingGps['radius_meter'] . "m.");
        }

        $guruModel = new GuruModel();
        $siswaModel = new SiswaModel();
        
        $user = $guruModel->where('nip', $qrContent)->first();
        $userType = 'guru';

        if (!$user) {
            if (strpos($qrContent, 'GURU-') === 0) {
                $guruId = str_replace('GURU-', '', $qrContent);
                $user = $guruModel->find($guruId);
            }
        }
        
        if (!$user) {
            $user = $siswaModel->where('nisn', $qrContent)->first();
            $userType = 'siswa';
        }

        if (!$user) {
            return $this->fail('QR Code tidak dikenali dalam database. Data Guru/Siswa tidak ditemukan.');
        }

        if ($jenisAbsen && $jenisAbsen != 'sekolah') {
            return $this->processAbsenKegiatan($user, $userType, $userLat, $userLong, $jenisAbsen);
        }

        $settingJamModel = new SettingJamModel();
        
        $hariInggris = date('l');
        $map = [
            'Sunday' => 'Minggu', 'Monday' => 'Senin', 'Tuesday' => 'Selasa',
            'Wednesday' => 'Rabu', 'Thursday' => 'Kamis', 'Friday' => 'Jumat', 'Saturday' => 'Sabtu'
        ];
        $hariIni = $map[$hariInggris];

        $jamSetting = $settingJamModel->where('type', $userType)
                                      ->where('hari', $hariIni)
                                      ->first();

        if (!$jamSetting) {
            return $this->fail("Jadwal absensi untuk hari $hariIni belum diatur oleh Admin.");
        }

        $absensiModel = new AbsensiModel();
        $tanggalHariIni = date('Y-m-d');
        $jamSekarang = date('H:i:s');

        $jamPulangAkhir = $jamSetting['jam_pulang_akhir'];
        if ($jamPulangAkhir == '00:00:00') {
            $jamPulangAkhir = '23:59:59';
        }

        if ($jamSekarang < $jamSetting['jam_masuk_mulai'] || $jamSekarang > $jamPulangAkhir) {
             return $this->fail("Absensi ditutup. Jam operasional hari $hariIni: " . substr($jamSetting['jam_masuk_mulai'], 0, 5) . " - " . substr($jamSetting['jam_pulang_akhir'], 0, 5));
        }

        $cekAbsen = $absensiModel->where('user_id', $user['id'])
                                 ->where('user_type', $userType)
                                 ->where('tanggal', $tanggalHariIni)
                                 ->first();

        if ($cekAbsen) {
            if ($cekAbsen['jam_pulang'] == null) {
                if ($jamSekarang < $jamSetting['jam_masuk_akhir']) { 
                    return $this->fail('Belum waktunya pulang. Anda baru saja absen masuk.');
                }

                $keteranganTambahan = "";
                if ($jamSekarang < $jamSetting['jam_pulang_mulai']) {
                    $keteranganTambahan = " (Cepat Pulang)";
                }

                $absensiModel->update($cekAbsen['id'], [
                    'jam_pulang' => $jamSekarang,
                    'keterangan' => trim(($cekAbsen['keterangan'] ?? '') . $keteranganTambahan),
                    'status' => ($keteranganTambahan != "") ? 'Cepat Pulang' : $cekAbsen['status']
                ]);

                $namaUser = ($userType == 'guru') ? $user['nama_guru'] : $user['nama_lengkap'];
                $nomorTarget = ($userType == 'guru') ? $user['no_wa'] : $user['no_wa_ortu'];
                
                $pesanWA = "*NOTIFIKASI PULANG*\n\n"
                         . "Nama: $namaUser\n"
                         . "Waktu: " . date('d-m-Y H:i') . " WIB\n"
                         . "Status: Pulang$keteranganTambahan\n\n"
                         . "Hati-hati di jalan.";
                
                $this->sendWhatsApp($nomorTarget, $pesanWA);

                return $this->respond([
                    'status' => 200,
                    'message' => 'Absen Pulang Berhasil!' . $keteranganTambahan,
                    'nama' => $namaUser,
                    'jam' => $jamSekarang
                ]);
            } else {
                return $this->fail('Anda sudah melakukan absen pulang hari ini.');
            }
        } else {
            if ($jamSekarang >= $jamSetting['jam_pulang_mulai']) {
                 return $this->fail('Waktu absen masuk sudah habis. Sekarang waktu pulang.');
            }

            $status = 'Hadir';
            $keterangan = '';

            if ($jamSekarang > $jamSetting['jam_masuk_akhir']) {
                $status = 'Terlambat';
                $keterangan = "Terlambat";
            }

            $absensiModel->insert([
                'user_type' => $userType,
                'user_id' => $user['id'],
                'tanggal' => $tanggalHariIni,
                'jam_masuk' => $jamSekarang,
                'status' => $status,
                'keterangan' => $keterangan,
                'lokasi_lat' => $userLat,
                'lokasi_long' => $userLong
            ]);

            $namaUser = ($userType == 'guru') ? $user['nama_guru'] : $user['nama_lengkap'];
            $nomorTarget = ($userType == 'guru') ? $user['no_wa'] : $user['no_wa_ortu'];
            
            $pesanWA = "*NOTIFIKASI MASUK*\n\n"
                      . "Nama: $namaUser\n"
                      . "Waktu: " . date('d-m-Y H:i') . " WIB\n"
                      . "Status: *$status*\n\n"
                      . "Terima kasih.";
            
            $this->sendWhatsApp($nomorTarget, $pesanWA);

            return $this->respond([
                'status' => 200,
                'message' => 'Absen Masuk Berhasil! Status: ' . $status,
                'nama' => $namaUser,
                'jam' => $jamSekarang,
                'status_kehadiran' => $status
            ]);
        }
    }

    private function processAbsenKegiatan($user, $userType, $lat, $long, $kodeJenis)
    {
        $parts = explode('_', $kodeJenis);
        if (count($parts) < 2) return $this->fail('Kode kegiatan tidak valid');
        
        $kategori = $parts[0];
        $kegiatanId = $parts[1];

        $modelSholat = new KegiatanSholatModel();
        $modelEkskul = new KegiatanEkskulModel();
        $absenKegiatanModel = new AbsensiKegiatanModel();

        $namaKegiatan = '';
        $jamMulai = '';
        $jamAkhir = '';

        if ($kategori == 'sholat') {
            $keg = $modelSholat->find($kegiatanId);
            if(!$keg) return $this->fail('Data Sholat tidak ditemukan.');
            $namaKegiatan = $keg['nama_sholat'];
            $jamMulai = $keg['jam_mulai'];
            $jamAkhir = $keg['jam_akhir'];
        } else {
            $keg = $modelEkskul->find($kegiatanId);
            if(!$keg) return $this->fail('Data Ekskul tidak ditemukan.');
            $namaKegiatan = $keg['nama_ekskul'];
            $jamMulai = $keg['jam_mulai'];
            $jamAkhir = $keg['jam_akhir'];
        }

        $jamSekarang = date('H:i:s');
        if ($jamSekarang < $jamMulai || $jamSekarang > $jamAkhir) {
            return $this->fail("Absen $namaKegiatan hanya bisa dilakukan pukul " . substr($jamMulai,0,5) . " - " . substr($jamAkhir,0,5));
        }

        $cek = $absenKegiatanModel->where('user_id', $user['id'])
                                  ->where('user_type', $userType)
                                  ->where('kategori', $kategori)
                                  ->where('kegiatan_id', $kegiatanId)
                                  ->where('tanggal', date('Y-m-d'))
                                  ->first();
        
        if ($cek) {
            return $this->fail("Anda sudah melakukan absen $namaKegiatan hari ini.");
        }

        $absenKegiatanModel->save([
            'user_type' => $userType,
            'user_id' => $user['id'],
            'kategori' => $kategori,
            'kegiatan_id' => $kegiatanId,
            'nama_kegiatan' => $namaKegiatan,
            'tanggal' => date('Y-m-d'),
            'jam_absen' => $jamSekarang,
            'status' => 'Hadir',
            'lokasi_lat' => $lat,
            'lokasi_long' => $long
        ]);

        $namaUser = ($userType == 'guru') ? $user['nama_guru'] : $user['nama_lengkap'];
        $nomorTarget = ($userType == 'guru') ? $user['no_wa'] : $user['no_wa_ortu'];

        $pesanWA = "*NOTIFIKASI KEGIATAN*\n\n"
                 . "Nama: $namaUser\n"
                 . "Kegiatan: $namaKegiatan\n"
                 . "Waktu: " . date('d-m-Y H:i') . " WIB\n"
                 . "Status: *Hadir*\n\n"
                 . "Terima kasih.";

        $this->sendWhatsApp($nomorTarget, $pesanWA);
        
        return $this->respond([
            'status' => 200, 
            'message' => "Absen $namaKegiatan Berhasil!", 
            'nama' => $namaUser, 
            'jam' => $jamSekarang
        ]);
    }

    private function calculateDistance($lat1, $lon1, $lat2, $lon2)
    {
        $earthRadius = 6371000;
        $lat1 = deg2rad($lat1);
        $lon1 = deg2rad($lon1);
        $lat2 = deg2rad($lat2);
        $lon2 = deg2rad($lon2);
        $latDelta = $lat2 - $lat1;
        $lonDelta = $lon2 - $lon1;
        $a = sin($latDelta / 2) * sin($latDelta / 2) + cos($lat1) * cos($lat2) * sin($lonDelta / 2) * sin($lonDelta / 2);
        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        return $earthRadius * $c;
    }

    private function sendWhatsApp($target, $message)
    {
        $settingModel = new \App\Models\SettingWhatsappModel();
        $config = $settingModel->first();

        if (!$config || empty($config['wa_gateway_url'])) {
            return false; 
        }

        $url = $config['wa_gateway_url'];
        $token = $config['wa_api_token'];

        $target = preg_replace('/[^0-9]/', '', $target);
        if (substr($target, 0, 1) == '0') {
            $target = '62' . substr($target, 1);
        }
        if (strpos($target, '@c.us') === false) {
            $target = $target . '@c.us'; 
        }

        $data = [
            'phone' => $target,
            'message' => $message,
        ];

        $curl = curl_init();

        curl_setopt_array($curl, array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => array(
                'Content-Type: application/json',
                'Authorization: ' . $token,
                'ngrok-skip-browser-warning: true'
            ),
        ));

        $response = curl_exec($curl);
        curl_close($curl);

        return $response;
    }
}