<?php

namespace App\Commands;

use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;

class SendDailySchedule extends BaseCommand
{
    /**
     * The Command's Group
     *
     * @var string
     */
    protected $group = 'Cron';

    /**
     * The Command's Name
     *
     * @var string
     */
    protected $name = 'app:send-daily-schedule';

    /**
     * The Command's Description
     *
     * @var string
     */
    protected $description = 'Kirim jadwal mengajar harian ke WhatsApp guru via Fonnte otomatis';

    /**
     * The Command's Options
     *
     * @var array
     */
    protected $options = [
        '-f, --force' => 'Abaikan pengecekan hari libur/Minggu dan kirim jadwal secara paksa',
        '-d, --day'   => 'Simulasikan pengiriman untuk hari tertentu (1 = Senin, ..., 7 = Minggu)'
    ];

    public function run(array $params)
    {
        // Matikan batas waktu eksekusi agar script tidak timeout karena jeda pengiriman (sleep)
        if (!ini_get('safe_mode')) {
            set_time_limit(0);
        }

        $db = \Config\Database::connect();
        
        $todayDate   = date('Y-m-d');
        $todayDayNum = (int)date('N'); // 1 = Senin, ..., 7 = Minggu

        log_message('info', "SendDailySchedule: Command started. Date: {$todayDate}, Day: {$todayDayNum}");

        // Ambil opsi dari terminal atau parameter programmatic
        $force = CLI::getOption('force') !== null;
        if (!$force) {
            if (array_key_exists('force', $params) || array_key_exists('f', $params) || in_array('--force', $params) || in_array('-f', $params)) {
                $force = true;
            }
        }

        $customDay = CLI::getOption('day');
        if ($customDay === null) {
            if (isset($params['day'])) {
                $customDay = $params['day'];
            } elseif (isset($params['d'])) {
                $customDay = $params['d'];
            } else {
                foreach ($params as $key => $val) {
                    // CI4 command() tokenizer mengubah '--day=1' menjadi key 'day=1' dengan value null
                    if (is_string($key) && str_starts_with($key, 'day=')) {
                        $customDay = substr($key, 4);
                        break;
                    }
                    if (is_string($key) && str_starts_with($key, 'd=')) {
                        $customDay = substr($key, 2);
                        break;
                    }
                    if (is_string($val) && str_starts_with($val, '--day=')) {
                        $customDay = substr($val, 6);
                        break;
                    }
                }
            }
        }

        if ($customDay !== null) {
            $todayDayNum = (int)$customDay;
            CLI::write("Mode Simulasi Hari ke-$todayDayNum", 'cyan');
        }

        CLI::write("=== MENJALANKAN CRON JADWAL HARIAN GURU ===", 'yellow');
        CLI::write("Tanggal: " . $todayDate . " (Hari ke-" . $todayDayNum . ")");

        if (!$force) {
            // 1. Cek Hari Minggu
            if ($todayDayNum === 7) {
                CLI::write("Hari ini adalah hari Minggu. Pengiriman dibatalkan.", 'light_blue');
                log_message('info', "SendDailySchedule: Hari ini Minggu, pengiriman dibatalkan.");
                return;
            }

            // 2. Cek Pengaturan Sabtu Libur
            $settingSabtu = $db->table('calendar_settings')->where('key', 'sabtu_libur')->get()->getRowArray();
            $sabtuLibur   = $settingSabtu && (int)$settingSabtu['value'] === 1;
            if ($todayDayNum === 6 && $sabtuLibur) {
                CLI::write("Hari ini adalah hari Sabtu dan dikonfigurasi Libur. Pengiriman dibatalkan.", 'light_blue');
                log_message('info', "SendDailySchedule: Hari ini Sabtu (Libur), pengiriman dibatalkan.");
                return;
            }

            // 3. Cek Libur Nasional / Kalender Pendidikan
            $holiday = $db->table('calendar_events ce')
                ->join('calendar_categories cc', 'cc.id = ce.category_id')
                ->where('cc.is_libur', 1)
                ->where('ce.deleted_at', null)
                ->where('ce.start_date <=', $todayDate)
                ->where('ce.end_date >=', $todayDate)
                ->get()->getRowArray();

            if ($holiday) {
                CLI::write("Hari ini Hari Libur Pendidikan: " . $holiday['title'] . ". Pengiriman dibatalkan.", 'light_blue');
                log_message('info', "SendDailySchedule: Hari ini libur nasional/sekolah (" . $holiday['title'] . "). Pengiriman dibatalkan.");
                return;
            }
        } else {
            CLI::write("Mode Force Aktif: Mengabaikan pengecekan hari libur/Minggu.", 'red');
        }

        // 4. Ambil Sumber Jadwal Terpilih (local vs asc)
        $sourceRow = $db->table('settings')->where('setting_key', 'schedule_source')->get()->getRowArray();
        $scheduleSource = $sourceRow['setting_value'] ?? 'local';
        CLI::write("Sumber Jadwal Aktif: " . strtoupper($scheduleSource));

        // 5. Ambil Tahun Pelajaran Aktif
        $activePeriod = $db->table('academic_periods')->where('is_active', 1)->get()->getRowArray();
        $periodId = $activePeriod ? $activePeriod['id'] : null;
        if (!$periodId && $scheduleSource === 'local') {
            CLI::error("Tidak ada periode akademik aktif. Pengiriman dibatalkan.");
            log_message('error', "SendDailySchedule: Periode akademik aktif tidak ditemukan.");
            return;
        }

        // Ambil Daftar Guru Aktif yang Memiliki Nomor WA
        $teachers = $db->table('teachers')
            ->where('deleted_at', null)
            ->where('phone !=', '')
            ->orderBy('name', 'ASC')
            ->get()->getResultArray();

        log_message('info', "SendDailySchedule: Found " . count($teachers) . " teachers with phone numbers.");

        if (empty($teachers)) {
            CLI::write("Tidak ada guru aktif dengan nomor telepon WhatsApp.", 'red');
            log_message('warning', "SendDailySchedule: Aborting because there are no teachers with phone numbers.");
            return;
        }

        // Persiapan Konfigurasi Hari/Tanggal Format Indonesia
        $daysMap = [
            1 => 'Senin', 2 => 'Selasa', 3 => 'Rabu', 4 => 'Kamis', 5 => 'Jumat', 6 => 'Sabtu', 7 => 'Minggu'
        ];
        $monthsMap = [
            1 => 'Januari', 2 => 'Februari', 3 => 'Maret', 4 => 'April', 5 => 'Mei', 6 => 'Juni',
            7 => 'Juli', 8 => 'Agustus', 9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Desember'
        ];
        $dayName = $daysMap[$todayDayNum] ?? '';
        $dateFormatted = date('d') . ' ' . ($monthsMap[(int)date('m')] ?? '') . ' ' . date('Y');
        $todayStringIndo = "$dayName, $dateFormatted";

        // Inisialisasi WhatsappService
        $waService = new \App\Services\WhatsappService();
        if (!$waService->isConfigured()) {
            CLI::error("Whatsapp Gateway belum terkonfigurasi dengan benar di Pengaturan!");
            log_message('error', "SendDailySchedule: WhatsApp Gateway belum terkonfigurasi.");
            return;
        }

        if (!$waService->isFeatureEnabled('schedule')) {
            CLI::write("Fitur pengiriman jadwal harian via WhatsApp dinonaktifkan di Pengaturan.", 'light_blue');
            log_message('info', "SendDailySchedule: Fitur pengiriman jadwal WhatsApp dinonaktifkan.");
            return;
        }

        $sentCount = 0;
        $skipCount = 0;

        foreach ($teachers as $teacher) {
            $todaySchedule = [];

            // Kueri Jadwal Berdasarkan Sumber
            if ($scheduleSource === 'asc') {
                $ascImportModel = new \App\Models\AscImportModel();
                $ascTeacherModel = new \App\Models\AscTeacherModel();
                $activeImport = $ascImportModel->getActive();
                
                if ($activeImport) {
                    $ascTeacher = $ascTeacherModel->where('import_id', $activeImport['id'])
                                                   ->where('teacher_id', $teacher['id'])
                                                   ->first();
                    if ($ascTeacher) {
                        $todaySchedule = $db->table('asc_schedules')
                            ->select('asc_schedules.*, 
                                      COALESCE(classrooms.name, asc_classes.name) as display_class_name,
                                      COALESCE(school_subjects.name, asc_subjects.name) as display_subject_name')
                            ->join('asc_subjects', 'asc_subjects.asc_id = asc_schedules.subject_asc_id AND asc_subjects.import_id = asc_schedules.import_id', 'left')
                            ->join('school_subjects', 'school_subjects.id = asc_subjects.school_subject_id', 'left')
                            ->join('asc_classes', 'asc_classes.asc_id = asc_schedules.class_asc_id AND asc_classes.import_id = asc_schedules.import_id', 'left')
                            ->join('classrooms', 'classrooms.id = asc_classes.classroom_id', 'left')
                            ->where('asc_schedules.import_id', $activeImport['id'])
                            ->where('asc_schedules.teacher_asc_id', $ascTeacher['asc_id'])
                            ->where('asc_schedules.day_number', $todayDayNum)
                            ->orderBy('asc_schedules.period_number', 'ASC')
                            ->get()
                            ->getResultArray();
                    }
                }
            } else {
                // Jalur Lokal
                $scheduleModel = new \App\Models\ScheduleModel();
                $publishedSchedule = $scheduleModel->where('academic_period_id', $periodId)
                                                    ->where('status', 'published')
                                                    ->where('type', $scheduleSource)
                                                    ->first();
                if ($publishedSchedule) {
                    $activeDays = array_map('intval', explode(',', $publishedSchedule['active_days']));
                    if (in_array($todayDayNum, $activeDays)) {
                        $todaySchedule = $db->table('schedule_entries se')
                            ->select([
                                'se.slot_number as period_number',
                                'c.name as display_class_name',
                                'ss.name as display_subject_name'
                            ])
                            ->join('classrooms c', 'c.id = se.classroom_id', 'left')
                            ->join('school_subjects ss', 'ss.id = se.school_subject_id', 'left')
                            ->where('se.schedule_id', $publishedSchedule['id'])
                            ->where('se.teacher_id', $teacher['id'])
                            ->where('se.day', $todayDayNum)
                            ->orderBy('se.slot_number', 'ASC')
                            ->get()->getResultArray();
                    }
                }
            }

            // Jika tidak ada jadwal mengajar, lewati guru ini
            if (empty($todaySchedule)) {
                $skipCount++;
                continue;
            }

            // Susun isi pesan
            helper('url');
            $baseUrl = rtrim(base_url(), '/');

            $msg  = "Assalamu'alaikum Wr. Wb. Bpk/Ibu *{$teacher['name']}* 🙏\n\n";
            $msg .= "Berikut adalah jadwal mengajar Anda hari ini, *{$todayStringIndo}*:\n\n";
            $msg .= "*JADWAL HARI INI:*\n";
            $msg .= "──────────────\n";
            foreach ($todaySchedule as $row) {
                $msg .= "⏰ Jam ke-{$row['period_number']}: Kelas {$row['display_class_name']} — {$row['display_subject_name']}\n";
            }
            $msg .= "──────────────\n\n";
            $msg .= "Jika berhalangan Hadir, mohon segera Konfirmasi ke guru Piket. Semoga hari Anda menyenangkan dan selamat mengajar! 🌟\n\n";
            $msg .= "_Pesan dikirim otomatis dari aplikasi SIMAK - {$baseUrl}_";

            // Kirim pesan WA
            $result = $waService->send($teacher['phone'], $msg);

            if ($result['success']) {
                $sentCount++;
                CLI::write("- Dikirim ke: " . $teacher['name'] . " (" . $teacher['phone'] . ")", 'green');
            } else {
                CLI::write("- GAGAL kirim ke: " . $teacher['name'] . ". Error: " . $result['message'], 'red');
                log_message('error', "SendDailySchedule: Gagal mengirim ke {$teacher['name']} ({$teacher['phone']}). Error: " . $result['message']);
            }

            // Beri jeda 120 detik (2 menit) untuk menghindari rate limit / blokir spam WA sesuai anjuran Fonnte
            sleep(120);

            // Sambungkan kembali koneksi DB setelah jeda panjang (mencegah "MySQL server has gone away")
            $db->reconnect();
        }

        CLI::write("\n=== SELESAI ===", 'yellow');
        CLI::write("Total dikirim: $sentCount | Guru dilewati (tidak mengajar): $skipCount");
        log_message('info', "SendDailySchedule: Selesai. Total dikirim: $sentCount, dilewati: $skipCount");
    }
}
