<?php
// controllers/PemesananController.php

// Ensure all necessary models are included.
// Using __DIR__ ensures the path is relative to the current file (PemesananController.php).
require_once __DIR__ . '/../models/Jadwal.php';
require_once __DIR__ . '/../models/Detail_Pemesanan.php';
require_once __DIR__ . '/../models/Users.php'; // Digunakan jika perlu data user langsung di controller (misal untuk logging/audit)
require_once __DIR__ . '/../models/Kursi.php'; // Digunakan untuk mendapatkan nomor kursi jika pemesanan gagal
require_once __DIR__ . '/BaseController.php'; // BaseController yang berisi method helper (requireAuth, isAdmin, dll.)

/**
 * Class PemesananController
 * Manages all logic related to ticket bookings, from seat selection to admin management.
 * Handles displaying forms, processing bookings, listing bookings, updating status, and fetching details.
 */
class PemesananController extends BaseController {

    /**
     * Constructor for PemesananController.
     * Accepts a MySQLi connection object and passes it to the BaseController.
     * @param mysqli $conn The MySQLi database connection object.
     */
    public function __construct(mysqli $conn) {
        parent::__construct($conn);
    }

    /**
     * Displays the seat selection form for a specific schedule.
     * Accessible only by logged-in users.
     *
     * @param int|null $jadwal_id The ID of the movie schedule.
     */
    public function showForm($jadwal_id = null) {
        $this->requireAuth(); // Ensures the user is logged in before accessing this page

        // Validate schedule ID from URL parameter
        if ($jadwal_id === null || !is_numeric($jadwal_id)) {
            $this->setErrorMessage("Jadwal tayang tidak dipilih atau ID tidak valid.");
            $this->redirect('film'); // Redirect to film list if ID is missing/invalid
            exit();
        }

        $jadwalModel = new Jadwal($this->conn);
        $jadwal_detail = $jadwalModel->getJadwalById($jadwal_id);

        // Check if the schedule was found in the database
        if (!$jadwal_detail) {
            $this->setErrorMessage("Jadwal tayang tidak ditemukan.");
            $this->redirect('film'); // Redirect if schedule does not exist
            exit();
        }

        // Get the current status of seats for this specific schedule
        // This is crucial to display which seats are available, booked, etc.
        $kursi_status = $jadwalModel->getKursiStatusByJadwal($jadwal_id);

        // Display the booking form view, passing the schedule details and seat statuses
        $this->view('form_pemesanan', ['jadwal_detail' => $jadwal_detail, 'kursi_status' => $kursi_status]);
    }

    /**
     * Processes POST data from the seat selection form.
     * Creates new booking entries in the database for each selected seat.
     */
    public function processPemesanan() {
        $this->requireAuth(); // Ensures the user is logged in to process a booking

        // Only process the form submission if the request method is POST
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            // Retrieve data from POST request, using null coalescing operator (??) for safety
            $user_id = $_SESSION['user_id'] ?? null;
            $jadwal_id = $_POST['jadwal_id'] ?? null;
            $selected_kursi_ids = $_POST['kursi_ids'] ?? []; // This is an array of selected seat IDs
            $payment_method = $_POST['payment_method'] ?? null; // The chosen payment method from hidden input

            // Basic input validation: ensure all necessary data is present
            if (empty($user_id) || empty($jadwal_id) || empty($selected_kursi_ids) || empty($payment_method)) {
                $this->setErrorMessage("Pilihan jadwal, kursi, atau metode pembayaran tidak valid, atau Anda belum login.");
                // Redirect back to the booking form with the schedule ID if available
                $this->redirect('pemesanan_form', ['jadwal_id' => $jadwal_id]);
                exit();
            }

            // Instantiate necessary models
            $jadwalModel = new Jadwal($this->conn);
            $detailPemesananModel = new Detail_Pemesanan($this->conn);

            // Fetch schedule information to get ticket price and verify existence
            $jadwal_info = $jadwalModel->getJadwalById($jadwal_id);
            if (!$jadwal_info) {
                $this->setErrorMessage("Jadwal tidak ditemukan.");
                $this->redirect('film_detail', ['id' => $jadwal_id]);
                exit();
            }

            $harga_tiket = $jadwal_info['harga_tiket']; // Get the ticket price for this schedule
            $success_count = 0; // Counter for successfully booked seats
            $failed_kursi_numbers = []; // Array to store seat numbers that failed to book

            // Loop through each selected seat ID and attempt to create a booking
            foreach ($selected_kursi_ids as $kursi_id) {
                $kursi_id = (int) $kursi_id; // Cast to integer to ensure correct data type
                
                // Call the createPemesanan method in the Detail_Pemesanan model
                // Pass all necessary data, including the selected payment method
                $result = $detailPemesananModel->createPemesanan($user_id, $jadwal_id, $kursi_id, $harga_tiket, 'pending', $payment_method);
                
                if ($result) {
                    $success_count++; // Increment success counter if booking was created
                } else {
                    // If booking fails, log the seat number
                    $kursiModel = new Kursi($this->conn);
                    $failed_kursi_info = $kursiModel->getKursiById($kursi_id);
                    // Add seat number (or ID if not found) to failed list
                    $failed_kursi_numbers[] = $failed_kursi_info ? $failed_kursi_info['nomor'] : 'ID: ' . $kursi_id;
                }
            }

            // Provide feedback to the user based on the overall booking results
            if ($success_count > 0) {
                $this->setSuccessMessage("Berhasil memesan " . $success_count . " kursi dengan metode " . htmlspecialchars(ucfirst(str_replace('_', ' ', $payment_method))) . ". Silakan lanjutkan pembayaran.");
                $this->redirect('pemesanan_list'); // Redirect to user's booking list
                exit();
            } else {
                // If all selected seats failed to book
                $errorMessage = "Gagal memesan kursi yang dipilih. Mungkin sudah terisi atau terjadi kesalahan.";
                if (!empty($failed_kursi_numbers)) {
                    $errorMessage .= " Kursi gagal: " . implode(', ', $failed_kursi_numbers);
                }
                $this->setErrorMessage($errorMessage);
                // Redirect back to the booking form to let the user try again
                $this->redirect('pemesanan_form', ['jadwal_id' => $jadwal_id]);
                exit();
            }

        } else {
            // If the request is not POST (e.g., direct access to this URL), redirect to film list
            $this->redirect('film');
            exit();
        }
    }

    /**
     * Displays a list of bookings for the currently logged-in user.
     * Accessible only by authenticated users.
     */
    public function list() {
        $this->requireAuth(); // Ensures the user is logged in

        $detailPemesananModel = new Detail_Pemesanan($this->conn);
        $user_id = $_SESSION['user_id']; // Get the logged-in user's ID
        $pemesanan_list = $detailPemesananModel->getPemesananByUser($user_id); // Fetch bookings for this user

        $this->view('pemesanan', ['pemesanan_list' => $pemesanan_list]); // Display the user's booking list view
    }

    /**
     * Displays all booking records in the system.
     * Restricted to admin users only.
     */
    public function all() {
        $this->requireAdmin(); // Ensures the user is an admin to access this functionality

        $detailPemesananModel = new Detail_Pemesanan($this->conn);
        $all_pemesanan = $detailPemesananModel->getAllPemesanan(); // Fetch all bookings from the database

        $this->view('pemesanan_admin_list', ['all_pemesanan' => $all_pemesanan]); // Display the admin's booking list view
    }

    /**
     * Updates the status of a specific booking.
     * Restricted to admin users only.
     *
     * @param int $pemesanan_id The ID of the booking detail to update.
     * @param string $status The new status ('paid', 'cancelled').
     */
    public function updateStatus($pemesanan_id, $status) {
        $this->requireAdmin(); // Ensures the user is an admin

        // Validate the new status against allowed values for security
        $allowed_statuses = ['paid', 'cancelled'];
        if (!in_array($status, $allowed_statuses)) {
            $this->setErrorMessage("Status tidak valid.");
            $this->redirect('pemesanan_all');
            exit();
        }

        $detailPemesananModel = new Detail_Pemesanan($this->conn);
        $result = $detailPemesananModel->updateStatusPemesanan($pemesanan_id, $status);

        if ($result) {
            $this->setSuccessMessage("Status pemesanan berhasil diperbarui menjadi '" . htmlspecialchars($status) . "'.");
        } else {
            $this->setErrorMessage("Gagal memperbarui status pemesanan.");
        }
        $this->redirect('pemesanan_all'); // Redirect back to the admin booking list
        exit();
    }

    /**
     * Retrieves the details of a single booking by its ID.
     * Returns data in JSON format for AJAX requests.
     * Accessible by authenticated users (for their own bookings) or admins (for any booking).
     *
     * @param int $pemesanan_id The ID of the booking detail.
     */
    public function getDetail($pemesanan_id) {
        $this->requireAuth(); // Ensures the user is logged in

        // Sanitize and validate the ID from the URL/request
        $pemesanan_id = filter_var($pemesanan_id, FILTER_SANITIZE_NUMBER_INT);

        if (!$pemesanan_id) {
            header('Content-Type: application/json');
            http_response_code(400); // Bad Request
            echo json_encode(['error' => 'Invalid booking ID.']);
            exit();
        }

        $detailPemesananModel = new Detail_Pemesanan($this->conn);
        $detail = $detailPemesananModel->getPemesananById($pemesanan_id);

        header('Content-Type: application/json'); // Set header for JSON response
        if ($detail) {
            // Security check: If not an admin, ensure the user is the owner of the booking
            if (!$this->isAdmin() && (!isset($_SESSION['user_id']) || $detail['users_id'] != $_SESSION['user_id'])) {
                 http_response_code(403); // Forbidden
                 echo json_encode(['error' => 'Akses ditolak. Ini bukan pesanan Anda atau Anda tidak memiliki izin.']);
                 exit();
            }

            echo json_encode($detail); // Return booking details as JSON
        } else {
            // If booking details are not found
            http_response_code(404); // Not Found
            echo json_encode(['error' => 'Booking details not found.']);
        }
        exit(); // Crucial: Stop script execution after sending JSON response
    }
}