<?php
// controllers/JadwalController.php

// Pastikan semua model yang relevan di-include
require_once __DIR__ . '/../models/Jadwal.php';
require_once __DIR__ . '/../models/Film.php';
require_once __DIR__ . '/../models/Studio.php'; // Mungkin diperlukan oleh FilmModel atau JadwalModel di beberapa metode
require_once __DIR__ . '/../models/Detail_Pemesanan.php'; // Diperlukan untuk pengecekan destroy
require_once __DIR__ . '/BaseController.php'; // BaseController yang berisi method helper (requireAuth, isAdmin, dll.)

/**
 * Class JadwalController
 * Mengelola semua logika terkait jadwal film, termasuk menampilkan, operasi CRUD,
 * dan pembuatan/pembersihan jadwal otomatis.
 */
class JadwalController extends BaseController {

    /**
     * Konstruktor untuk JadwalController.
     * Menerima objek koneksi MySQLi dan meneruskannya ke BaseController.
     * @param mysqli $conn Objek koneksi database MySQLi.
     */
    public function __construct(mysqli $conn) {
        parent::__construct($conn);
    }

    /**
     * Menampilkan daftar semua jadwal tayang yang akan datang.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal
     */
    public function index() {
        // Memerlukan peran admin untuk melihat dan mengelola jadwal
        $this->requireAdmin();

        // Panggil fungsi untuk memastikan jadwal selalu up-to-date
        // Ini akan menjalankan logika daur ulang/generate jadwal setiap kali halaman jadwal diakses
        $this->ensureSchedulesUpToDate();

        $jadwalModel = new Jadwal($this->conn);
        $all_jadwal = $jadwalModel->getAllJadwal(); // Ambil semua jadwal dari model

        // Load view untuk menampilkan daftar jadwal
        $this->view('jadwal', ['jadwal' => $all_jadwal]);
    }

    /**
     * Metode untuk mengelola jadwal secara otomatis:
     * 1. Menghapus jadwal yang sudah lewat tanggalnya.
     * 2. Menambahkan jadwal baru untuk mengisi kekosongan hingga 7 hari ke depan.
     * Dipicu setiap kali index() dipanggil atau dari generateSchedules().
     *
     * @return int Jumlah jadwal baru yang berhasil ditambahkan.
     */
    public function ensureSchedulesUpToDate() {
        $jadwalModel = new Jadwal($this->conn);
        $filmModel = new Film($this->conn);

        // Set timezone untuk konsistensi DateTime di PHP
        // Pastikan ini sudah diatur juga di index.php
        date_default_timezone_set('Asia/Jakarta');
        $bekasiTimezone = new DateTimeZone('Asia/Jakarta');

        $today = new DateTime('now', $bekasiTimezone);
        $today->setTime(0, 0, 0); // Atur ke awal hari ini untuk perbandingan tanggal

        $sevenDaysFromToday = clone $today;
        $sevenDaysFromToday->modify('+7 days'); // Tanggal 7 hari dari sekarang (batas akhir jadwal)

        // 1. Hapus jadwal yang sudah lewat tanggalnya (lebih kecil dari hari ini)
        // Ini memastikan hanya jadwal masa depan yang tersisa.
        $jadwalModel->deleteOldSchedules($today->format('Y-m-d'));

        // 2. Dapatkan tanggal jadwal terakhir yang ada di DB
        $lastScheduleDateStr = $jadwalModel->getLastScheduleDate();

        // Tentukan tanggal mulai generate jadwal baru.
        // Jika belum ada jadwal (lastScheduleDateStr is null), mulai generate dari hari ini.
        // Jika ada jadwal, mulai generate dari hari setelah jadwal terakhir yang ada.
        $startDateForGeneration = new DateTime($lastScheduleDateStr ? $lastScheduleDateStr : $today->format('Y-m-d'), $bekasiTimezone);
        $startDateForGeneration->setTime(0,0,0); // Atur ke awal hari untuk perbandingan tanggal

        // Atur currentDateToGenerate untuk selalu mulai dari hari berikutnya dari tanggal terakhir yang ada.
        // Ini mencegah duplikasi jika jadwal terakhir adalah hari ini dan kita generate untuk hari yang sama.
        $currentDateToGenerate = clone $startDateForGeneration;
        $currentDateToGenerate->modify('+1 day');

        // Dapatkan semua film untuk dijadwalkan
        $allFilms = $filmModel->getAllFilms();

        // Waktu tayang standar dengan harga tiket yang sudah ditentukan per slot
        // Harga ini yang akan digunakan untuk semua film yang dijadwalkan secara otomatis
        $timeSlots = [
            ['time' => '10:00:00', 'price' => 35000.00],
            ['time' => '13:00:00', 'price' => 35000.00],
            ['time' => '16:00:00', 'price' => 35000.00],
            ['time' => '19:00:00', 'price' => 40000.00], // Harga malam bisa lebih tinggi
            ['time' => '22:00:00', 'price' => 40000.00],
        ];

        $insertedCount = 0; // Hitung jadwal yang baru dibuat

        // Loop dan generate jadwal sampai 7 hari ke depan tercapai dari hari ini
        while ($currentDateToGenerate <= $sevenDaysFromToday) {
            foreach ($allFilms as $film) {
                // Untuk memastikan jadwal terikat dengan studio film yang benar
                // FilmModel::getAllFilms() harus mengembalikan studio_id
                if (!isset($film['studio_id'])) {
                    error_log("Film ID {$film['id']} does not have 'studio_id'. Skipping schedule generation for this film.");
                    continue; // Lewati film ini jika studio_id tidak ada
                }

                foreach ($timeSlots as $slot) {
                    $tanggal_untuk_jadwal = $currentDateToGenerate->format('Y-m-d');
                    
                    // --- PERUBAHAN KRUSIAL DI SINI ---
                    // Buat objek DateTime lengkap untuk tanggal dan waktu slot ini
                    // Ini memastikan MySQL menerima format waktu yang solid dari objek DateTime
                    try {
                        $dateTimeObj = new DateTime($tanggal_untuk_jadwal . ' ' . $slot['time'], $bekasiTimezone);
                        $waktu_untuk_jadwal = $dateTimeObj->format('H:i:s'); // Format ulang menjadi HH:MM:SS
                    } catch (Exception $e) {
                        error_log("Error creating DateTime object for slot '{$slot['time']}': " . $e->getMessage());
                        // Fallback ke string asli jika ada masalah, tapi ini tidak diharapkan
                        $waktu_untuk_jadwal = $slot['time']; 
                    }
                    // --- AKHIR PERUBAHAN KRUSIAL ---


                    // DEBUGGING FINAL CHECK (biarkan ini tetap ada untuk konfirmasi)
                    error_log("DEBUG FINAL CHECK: Mengirim ke model - Film ID: {$film['id']}, Tanggal: {$tanggal_untuk_jadwal}, Waktu: {$waktu_untuk_jadwal}, Harga: {$slot['price']}");


                    // Cek apakah jadwal ini sudah ada untuk film, tanggal, dan waktu ini
                    $existingJadwal = $jadwalModel->getJadwalByFilmDateAndTime(
                        $film['id'],
                        $tanggal_untuk_jadwal,
                        $waktu_untuk_jadwal // Gunakan waktu yang sudah diproses oleh DateTime
                    );

                    if (!$existingJadwal) {
                        // Buat jadwal baru jika belum ada
                        $result = $jadwalModel->createJadwal(
                            $film['id'],
                            $tanggal_untuk_jadwal,
                            $waktu_untuk_jadwal, // Gunakan waktu yang sudah diproses oleh DateTime
                            $slot['price']
                        );
                        if ($result) {
                            $insertedCount++;
                            error_log("DEBUG: createJadwal - SQL Execute BERHASIL.");
                        } else {
                            error_log("Failed to create schedule for Film ID: {$film['id']} on {$tanggal_untuk_jadwal} at {$waktu_untuk_jadwal}");
                        }
                    }
                }
            }
            $currentDateToGenerate->modify('+1 day'); // Maju ke hari berikutnya untuk digenerate
        }
        return $insertedCount; // Mengembalikan jumlah jadwal yang dibuat
    }


    /**
     * Menampilkan formulir untuk menambah jadwal baru secara manual.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_create
     */
    public function create() {
        $this->requireAdmin();

        $filmModel = new Film($this->conn);
        $films = $filmModel->getAllFilms(); // Mengambil semua film untuk dropdown di form

        $this->view('jadwal_form', ['films' => $films]); // Pastikan ini mengarah ke jadwal_form.php
    }

    /**
     * Memproses data POST dari formulir penambahan jadwal baru.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_store
     */
    public function store() {
        $this->requireAdmin();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $film_id = $_POST['film_id'] ?? null;
            $tanggal_tayang = $_POST['tanggal_tayang'] ?? null;
            $waktu_tayang = $_POST['waktu_tayang'] ?? null;
            $harga_tiket = $_POST['harga_tiket'] ?? null;

            // Validasi input
            if (empty($film_id) || empty($tanggal_tayang) || empty($waktu_tayang) || !is_numeric($harga_tiket) || $harga_tiket < 0) {
                $this->setErrorMessage("Data jadwal tidak lengkap atau harga tidak valid.");
                $this->redirect('jadwal_create');
                exit();
            }

            $jadwalModel = new Jadwal($this->conn);
            // Panggil createJadwal di model (nama method disesuaikan dengan Jadwal.php)
            $result = $jadwalModel->createJadwal($film_id, $tanggal_tayang, $waktu_tayang, (float)$harga_tiket);

            if ($result) {
                $this->setSuccessMessage("Jadwal berhasil ditambahkan.");
                $this->redirect('jadwal');
                exit();
            } else {
                $this->setErrorMessage("Gagal menambahkan jadwal. Mungkin jadwal duplikat untuk film dan waktu yang sama, atau ada kendala database.");
                $this->redirect('jadwal_create');
                exit();
            }
        } else {
            $this->redirect('jadwal_create'); // Redirect jika bukan POST request
        }
    }

    /**
     * Menampilkan formulir untuk mengedit jadwal yang sudah ada.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_edit&id=X
     * @param int $jadwal_id ID jadwal yang akan diedit.
     */
    public function edit($jadwal_id) {
        $this->requireAdmin();

        $jadwalModel = new Jadwal($this->conn);
        $filmModel = new Film($this->conn);

        $jadwal = $jadwalModel->getJadwalById($jadwal_id); // Mengambil detail jadwal
        $films = $filmModel->getAllFilms(); // Mengambil daftar film untuk dropdown

        if (!$jadwal) {
            $this->setErrorMessage("Jadwal tidak ditemukan.");
            $this->redirect('jadwal');
            exit();
        }

        $this->view('jadwal_form_update', ['jadwal' => $jadwal, 'films' => $films]); // Pastikan view ini ada
    }

    /**
     * Memproses data POST dari formulir pembaruan jadwal.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_update
     */
    public function update() {
        $this->requireAdmin();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $id = $_POST['id'] ?? null;
            $film_id = $_POST['film_id'] ?? null;
            $tanggal_tayang = $_POST['tanggal_tayang'] ?? null;
            $waktu_tayang = $_POST['waktu_tayang'] ?? null;
            $harga_tiket = $_POST['harga_tiket'] ?? null;

            // Validasi input
            if (empty($id) || empty($film_id) || empty($tanggal_tayang) || empty($waktu_tayang) || !is_numeric($harga_tiket) || $harga_tiket < 0) {
                $this->setErrorMessage("Data tidak lengkap atau harga tidak valid untuk pembaruan jadwal.");
                $this->redirect('jadwal_edit', ['id' => $id]); // Redirect kembali ke form edit
                exit();
            }

            $jadwalModel = new Jadwal($this->conn);
            // Panggil updateJadwal di model (nama method disesuaikan dengan Jadwal.php)
            $result = $jadwalModel->updateJadwal($id, $film_id, $tanggal_tayang, $waktu_tayang, (float)$harga_tiket);

            if ($result) {
                $this->setSuccessMessage("Jadwal berhasil diperbarui.");
                $this->redirect('jadwal');
                exit();
            } else {
                $this->setErrorMessage("Gagal memperbarui jadwal. Mungkin jadwal duplikat untuk film dan waktu yang sama, atau ada kendala database.");
                $this->redirect('jadwal_edit', ['id' => $id]);
                exit();
            }
        } else {
            $this->redirect('jadwal'); // Redirect jika bukan POST request
        }
    }

    /**
     * Menghapus jadwal tayang dari database.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_destroy&id=X
     * @param int $jadwal_id ID jadwal yang akan dihapus.
     */
    public function destroy($jadwal_id) {
        $this->requireAdmin();

        $jadwalModel = new Jadwal($this->conn);
        $detailPemesananModel = new Detail_Pemesanan($this->conn);

        // Cek apakah ada pemesanan terkait jadwal ini sebelum menghapus
        if ($detailPemesananModel->getPemesananCountByJadwal($jadwal_id) > 0) {
            $this->setErrorMessage("Tidak bisa menghapus jadwal. Ada pemesanan terkait jadwal ini.");
            $this->redirect('jadwal');
            exit();
        }

        $result = $jadwalModel->deleteJadwal($jadwal_id);

        if ($result) {
            $this->setSuccessMessage("Jadwal berhasil dihapus.");
        } else {
            $this->setErrorMessage("Gagal menghapus jadwal. Kendala database.");
        }
        $this->redirect('jadwal');
        exit();
    }

    /**
     * Menangani penghapusan jadwal secara massal.
     * Hanya untuk admin.
     * Dipanggil oleh index.php?hal=jadwal_bulk_destroy
     */
    public function bulk_destroy() {
        $this->requireAdmin();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $selected_ids = $_POST['selected_ids'] ?? [];

            if (empty($selected_ids) || !is_array($selected_ids)) {
                $this->setErrorMessage("Tidak ada jadwal yang dipilih untuk dihapus.");
                $this->redirect('jadwal');
                exit();
            }

            $jadwalModel = new Jadwal($this->conn);
            $detailPemesananModel = new Detail_Pemesanan($this->conn);
            $deleted_count = 0;
            $failed_count = 0;
            $failed_ids_with_bookings = [];

            foreach ($selected_ids as $id) {
                $id = (int)$id;

                if ($detailPemesananModel->getPemesananCountByJadwal($id) > 0) {
                    error_log("Percobaan menghapus jadwal ID {$id} gagal: Ditemukan pemesanan terkait.");
                    $failed_count++;
                    $failed_ids_with_bookings[] = $id;
                } else {
                    if ($jadwalModel->deleteJadwal($id)) {
                        $deleted_count++;
                    } else {
                        error_log("Gagal menghapus jadwal ID {$id} karena masalah database.");
                        $failed_count++;
                    }
                }
            }

            if ($deleted_count > 0 && $failed_count == 0) {
                $this->setSuccessMessage("Berhasil menghapus {$deleted_count} jadwal yang dipilih.");
            } elseif ($deleted_count > 0 && $failed_count > 0) {
                $message = "Berhasil menghapus {$deleted_count} jadwal.";
                if (!empty($failed_ids_with_bookings)) {
                    $message .= " Namun, {$failed_count} jadwal (ID: " . implode(', ', $failed_ids_with_bookings) . ") gagal dihapus karena ada pemesanan terkait.";
                } else {
                    $message .= " Namun, {$failed_count} jadwal gagal dihapus karena kendala lainnya.";
                }
                $this->setInfoMessage($message);
            } elseif ($deleted_count == 0 && $failed_count > 0) {
                $message = "Gagal menghapus jadwal. ";
                if (!empty($failed_ids_with_bookings)) {
                    $message .= "Semua jadwal yang dipilih (" . implode(', ', $failed_ids_with_bookings) . ") memiliki pemesanan terkait.";
                } else {
                    $message .= "Ada kendala saat menghapus jadwal yang dipilih.";
                }
                $this->setErrorMessage($message);
            } else {
                $this->setInfoMessage("Tidak ada jadwal yang dihapus.");
            }

            $this->redirect('jadwal');
            exit();
        } else {
            $this->redirect('jadwal');
            exit();
        }
    }

    /**
     * Memicu pembuatan jadwal otomatis untuk seminggu ke depan.
     * Ini bisa dipanggil manual dari URL (misal untuk testing),
     * atau dipanggil otomatis di index() atau cron job.
     * Menggunakan logika ensureSchedulesUpToDate().
     * Dipanggil oleh index.php?hal=jadwal_generate
     */
    public function generateSchedules() {
        $this->requireAdmin();

        $inserted_count = $this->ensureSchedulesUpToDate();

        if ($inserted_count > 0) {
            $this->setSuccessMessage("Berhasil membuat " . $inserted_count . " jadwal baru untuk seminggu ke depan.");
        } else {
            $this->setInfoMessage("Tidak ada jadwal baru yang ditambahkan. Mungkin jadwal sudah lengkap atau tidak ada film aktif.");
        }

        $this->redirect('jadwal');
    }
}