<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Http\Exception\NotFoundException;
use Cake\Mailer\Mailer;

class BookingController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();

        if ($this->components()->has('Authentication')) {
            $this->Authentication->allowUnauthenticated(['index', 'invoice']);
        }
    }

    public function index()
    {
        $bookingsTable = $this->fetchTable('Bookings');
        $booking = $bookingsTable->newEmptyEntity();
        $saveErrorMessage = null;

        if ($this->request->is('post')) {
            $data = $this->request->getData();

            $specialHandling = $data['special_handling'] ?? [];
            if (is_array($specialHandling)) {
                $data['special_handling'] = json_encode(array_values($specialHandling));
            } else {
                $data['special_handling'] = json_encode([]);
            }

            $data['booking_reference'] = $this->generateBookingReference();

            $booking = $bookingsTable->patchEntity($booking, $data);

            if ($booking->hasErrors()) {
                $saveErrorMessage = 'Please check all required fields and try again.';
            } else {
                if ($bookingsTable->save($booking)) {
                    $decodedSpecialHandling = [];

                    if (!empty($booking->special_handling)) {
                        $decoded = json_decode((string)$booking->special_handling, true);
                        if (is_array($decoded)) {
                            $decodedSpecialHandling = $decoded;
                        }
                    }

                    try {
                        $mailer = new Mailer('internal');

                        $mailer->setFrom(['brewhub@u25s2212.iedev.org' => 'Impeccable Courier'])
                            ->setTo($booking->shipper_email)
                            ->setSubject('Booking Confirmation - ' . $booking->booking_reference)
                            ->setEmailFormat('text')
                            ->setViewVars([
                                'booking' => $booking,
                                'specialHandling' => $decodedSpecialHandling,
                            ]);

                        $mailer->viewBuilder()->setTemplate('booking_confirmation');

                        $mailer->deliver();
                    } catch (\Exception $e) {
                        // Optional: log the error if email fails
                        // $this->log($e->getMessage(), 'error');
                    }

                    $this->set('booking', $booking);
                    $this->set('specialHandling', $decodedSpecialHandling);

                    return $this->render('invoice');
                }

                $saveErrorMessage = 'Your booking could not be saved. Please try again.';
            }
        }

        $this->set(compact('booking', 'saveErrorMessage'));
    }

    public function invoice()
    {
        throw new NotFoundException('Please submit a booking form first.');
    }

    private function generateBookingReference(): string
    {
        $bookingsTable = $this->fetchTable('Bookings');

        do {
            $reference = 'IC-' . date('Ymd') . '-' . strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));
            $exists = $bookingsTable->find()
                ->where(['booking_reference' => $reference])
                ->count() > 0;
        } while ($exists);

        return $reference;
    }
}