<?php

namespace App\Models;

use CodeIgniter\Model;
use App\Models\LiburNasionalModel;

class AbsensiModel extends Model
{
    protected $table            = 'absensi';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $allowedFields    = [
        'user_type', 'user_id', 'tanggal', 'jam_masuk', 'jam_pulang', 
        'status', 'keterangan', 'lokasi_lat', 'lokasi_long'
    ];

    // Helper untuk mapping hari Inggris -> Indo
    private function getHariIndo($dateStr) {
        $hariInggris = date('l', strtotime($dateStr));
        $map = [
            'Sunday' => 'Minggu', 'Monday' => 'Senin', 'Tuesday' => 'Selasa',
            'Wednesday' => 'Rabu', 'Thursday' => 'Kamis', 'Friday' => 'Jumat', 'Saturday' => 'Sabtu'
        ];
        return $map[$hariInggris];
    }

    // Ambil Setting Hari Efektif dari DB dan ubah jadi array simple
    private function getSettingHariArray() {
        $db = \Config\Database::connect();
        $settings = $db->table('setting_hari')->get()->getResultArray();
        $result = [];
        foreach ($settings as $s) {
            $result[$s['nama_hari']] = $s['tampilkan']; // 1 atau 0
        }
        return $result;
    }

    // Helper ambil array tanggal libur nasional dalam range tertentu
    private function getLiburDates($startDate, $endDate) {
        $liburModel = new LiburNasionalModel();
        // Ambil semua libur yang beririsan dengan range laporan
        $liburData = $liburModel->where('tanggal_akhir >=', $startDate)
                                ->where('tanggal_mulai <=', $endDate)
                                ->findAll();
        
        $blockedDates = [];
        foreach ($liburData as $l) {
            $period = new \DatePeriod(
                new \DateTime($l['tanggal_mulai']),
                new \DateInterval('P1D'),
                (new \DateTime($l['tanggal_akhir']))->modify('+1 day')
            );
            foreach ($period as $dt) {
                $blockedDates[] = $dt->format('Y-m-d');
            }
        }
        return $blockedDates;
    }

    public function getLaporan($tanggalAwal, $tanggalAkhir, $userType = null, $kelasId = null)
    {
        $db = \Config\Database::connect();
        
        // 1. Ambil Setting Hari & Libur Nasional
        $settingHari = $this->getSettingHariArray();
        $liburNasionalDates = $this->getLiburDates($tanggalAwal, $tanggalAkhir);

        // 2. Ambil Daftar User
        $users = [];
        if ($userType == 'guru') {
            $users = $db->table('guru')
                        ->select('id, nama_guru as nama_lengkap, nip as nomor_induk, jabatan')
                        ->orderBy('nama_guru', 'ASC')
                        ->get()->getResultArray();
        } else {
            $builder = $db->table('siswa')
                          ->select('siswa.id, siswa.nama_lengkap, siswa.nisn as nomor_induk, kelas.nama_kelas, kelas.jurusan')
                          ->join('kelas', 'siswa.kelas_id = kelas.id', 'left');
            if ($kelasId) {
                $builder->where('siswa.kelas_id', $kelasId);
            }
            $users = $builder->orderBy('siswa.nama_lengkap', 'ASC')->get()->getResultArray();
        }

        // 3. Ambil Data Absensi Existing
        $builder = $this->where('user_type', $userType)
                        ->where('tanggal >=', $tanggalAwal)
                        ->where('tanggal <=', $tanggalAkhir);
        $existingAbsensi = $builder->findAll();

        $mapAbsensi = [];
        foreach ($existingAbsensi as $absen) {
            $mapAbsensi[$absen['tanggal']][$absen['user_id']] = $absen;
        }

        // 4. Generate Data Harian
        $finalData = [];
        $currentDate = strtotime($tanggalAwal);
        $endDate = strtotime($tanggalAkhir);
        $today = strtotime(date('Y-m-d'));

        while ($currentDate <= $endDate) {
            // Stop jika lewat hari ini
            if ($currentDate > $today) break;

            $dateStr = date('Y-m-d', $currentDate);
            $namaHari = $this->getHariIndo($dateStr);
            
            // Cek apakah hari ini Setting Print (Minggu/Sabtu) ditampilkan?
            $isEfektif = isset($settingHari[$namaHari]) ? $settingHari[$namaHari] : 1;
            
            // Cek apakah hari ini Libur Nasional?
            $isLiburNasional = in_array($dateStr, $liburNasionalDates);

            foreach ($users as $u) {
                // Base Data
                $row = $u; 
                $row['tanggal'] = $dateStr;
                $row['user_type'] = $userType;
                $row['user_id'] = $u['id'];
                if ($userType == 'siswa' && isset($u['nama_kelas'])) {
                     $row['nama_kelas'] = $u['nama_kelas'] . ' ' . ($u['jurusan'] ?? '');
                }

                // Cek Absensi Database
                if (isset($mapAbsensi[$dateStr][$u['id']])) {
                    // Ada Data (Hadir/Sakit/Izin/Terlambat) -> Tampilkan apa adanya
                    $abs = $mapAbsensi[$dateStr][$u['id']];
                    $row = array_merge($row, $abs);
                    $finalData[] = $row;
                } else {
                    // Tidak Ada Data -> Cek apakah harus generate ALFA?
                    
                    // Logic: Generate ALFA hanya jika Hari Efektif DAN BUKAN Libur Nasional
                    if ($isEfektif == 1 && !$isLiburNasional) {
                        $row['id'] = null;
                        $row['jam_masuk'] = '-';
                        $row['jam_pulang'] = '-';
                        $row['status'] = 'Alfa';
                        $row['keterangan'] = '-';
                        $row['lokasi_lat'] = null;
                        $row['lokasi_long'] = null;
                        $finalData[] = $row;
                    }
                    // Jika Libur Nasional atau Hari Tidak Efektif -> SKIP (Tidak muncul di laporan)
                }
            }
            $currentDate = strtotime("+1 day", $currentDate);
        }

        // Sort
        usort($finalData, function($a, $b) {
            if ($a['tanggal'] == $b['tanggal']) {
                return strcmp($a['nama_lengkap'], $b['nama_lengkap']);
            }
            return strcmp($a['tanggal'], $b['tanggal']);
        });

        return $finalData;
    }

    public function getKoreksiData($tglAwal, $tglAkhir, $userType, $kelasId = null)
    {
        return $this->getLaporan($tglAwal, $tglAkhir, $userType, $kelasId);
    }

    public function getRekapBulanan($bulan, $tahun, $userType, $kelasId = null)
    {
        $builder = $this->db->table($this->table);
        $builder->select('absensi.user_id, DAY(absensi.tanggal) as hari, absensi.status');
        
        if ($userType == 'siswa' && $kelasId) {
            $builder->join('siswa', 'siswa.id = absensi.user_id', 'left');
            $builder->where('siswa.kelas_id', $kelasId);
        }

        $builder->where('absensi.user_type', $userType);
        $builder->where('MONTH(absensi.tanggal)', $bulan);
        $builder->where('YEAR(absensi.tanggal)', $tahun);
        
        $query = $builder->get()->getResultArray();

        $rekap = [];
        foreach ($query as $row) {
            $kode = strtoupper(substr($row['status'], 0, 1));
            if ($row['status'] == 'Cepat Pulang') $kode = 'H';
            $rekap[$row['user_id']][$row['hari']] = $kode;
        }
        return $rekap;
    }
}