<?php
declare(strict_types=1);

namespace App\Controller;

use Stripe\Stripe;
use Stripe\Checkout\Session;
use Cake\Routing\Router;

class BookingsController extends AppController
{
    public function add()
    {
        $this->viewBuilder()->setTemplatePath('Pages');
        $this->viewBuilder()->setTemplate('booking');

        $user = $this->request->getAttribute('identity');
        $lessons = $this->fetchTable('Lessons')->find()->all();

        if ($this->request->is('post')) {
            if ($user === null) {
                $this->Flash->warning('Sign in to book a class', [
                    'params' => [
                        'subtitle' => 'Log in or create an account, then return to booking to reserve your spot.',
                        'actionUrl' => Router::url(['controller' => 'Bookings', 'action' => 'add']),
                        'actionLabel' => 'Back to booking',
                    ],
                ]);

                return $this->redirect(['controller' => 'Bookings', 'action' => 'add']);
            }

            $data = $this->request->getData();

            $booking = $this->fetchTable('Bookings')->newEmptyEntity();
            $booking->user_id = $user->id;
            $booking->lesson_id = $data['lesson_id'];
            $booking->booking_date = $data['booking_date'];
            $booking->status = 'pending';

            if ($this->Bookings->save($booking)) {

                $payment = $this->fetchTable('Payments')->newEmptyEntity();
                $payment->booking_id = $booking->id;
                $payment->payment_method = 'stripe';
                $payment->payment_status = 'unpaid';

                $this->fetchTable('Payments')->save($payment);

                // Stripe setup
                Stripe::setApiKey('sk_test_51THOV3BHipzMdjWU4iZlMSgPkB1tXcLn5ZMG0u4LF8gekWD3huSSyAwwP3wmhhOYbnXN6T4lwYrhsCCN1b65qpsz007HH1XR6W');

                $lesson = $this->fetchTable('Lessons')->get($booking->lesson_id);

                $session = Session::create([
                    'payment_method_types' => ['card'],
                    'mode' => 'payment',
                    'line_items' => [[
                        'price_data' => [
                            'currency' => 'usd',
                            'product_data' => [
                                'name' => $lesson->lesson_name,
                            ],
                            'unit_amount' => (int)$lesson->price * 100,
                        ],
                        'quantity' => 1,
                    ]],
                    'success_url' => Router::url(['action' => 'success', $payment->id], true),
                    'cancel_url' => Router::url(['action' => 'cancelPayment', $payment->id], true),
                ]);

                return $this->redirect($session->url);
            }
        }

        $bookings = [];
        if ($user !== null) {
            $bookings = $this->Bookings->find()
                ->where([
                    'Bookings.user_id' => $user->id,
                    'Bookings.status !=' => 'cancelled',
                ])
                ->contain(['Lessons', 'Payments'])
                ->order(['Bookings.created' => 'DESC'])
                ->all();
        }

        $prefillLessonId = $this->request->getQuery('lesson_id');
        $prefillBookingDate = $this->request->getQuery('booking_date');
        if ($prefillLessonId !== null && $prefillLessonId !== '' && ctype_digit((string)$prefillLessonId)) {
            $prefillLessonId = (int)$prefillLessonId;
            $validIds = [];
            foreach ($lessons as $l) {
                $validIds[] = (int)$l->id;
            }
            if (!in_array($prefillLessonId, $validIds, true)) {
                $prefillLessonId = null;
            }
        } else {
            $prefillLessonId = null;
        }
        if ($prefillBookingDate !== null && $prefillBookingDate !== '') {
            $bd = (string)$prefillBookingDate;
            if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $bd)) {
                $prefillBookingDate = null;
            } else {
                $prefillBookingDate = $bd;
            }
        } else {
            $prefillBookingDate = null;
        }

        $this->set(compact('lessons', 'bookings', 'prefillLessonId', 'prefillBookingDate'));
    }

    public function success($paymentId)
    {
        $payment = $this->fetchTable('Payments')->get($paymentId, contain: ['Bookings']);

        $payment->payment_status = 'paid';
        $this->fetchTable('Payments')->save($payment);

        $booking = $payment->booking;
        $booking->status = 'confirmed';
        $this->Bookings->save($booking);

        return $this->redirect(['action' => 'add']);
    }

    public function cancelPayment($paymentId)
    {
        return $this->redirect(['action' => 'add']);
    }

    public function payAgain($paymentId)
    {
        $payment = $this->fetchTable('Payments')
            ->get($paymentId, contain: ['Bookings' => ['Lessons']]);

        if ($payment->payment_status === 'paid') {
            return $this->redirect(['action' => 'add']);
        }

        Stripe::setApiKey('sk_test_51THOV3BHipzMdjWU4iZlMSgPkB1tXcLn5ZMG0u4LF8gekWD3huSSyAwwP3wmhhOYbnXN6T4lwYrhsCCN1b65qpsz007HH1XR6W');

        $lesson = $payment->booking->lesson;

        $session = Session::create([
            'payment_method_types' => ['card'],
            'mode' => 'payment',
            'line_items' => [[
                'price_data' => [
                    'currency' => 'usd',
                    'product_data' => [
                        'name' => $lesson->lesson_name,
                    ],
                    'unit_amount' => (int)$lesson->price * 100,
                ],
                'quantity' => 1,
            ]],
            'success_url' => Router::url(['action' => 'success', $payment->id], true),
            'cancel_url' => Router::url(['action' => 'cancelPayment', $payment->id], true),
        ]);

        return $this->redirect($session->url);
    }

    public function cancel($id)
    {
        $this->request->allowMethod(['post']);

        $user = $this->request->getAttribute('identity');
        $booking = $this->Bookings->get($id);

        if ($user === null || (int)$booking->user_id !== (int)$user->id) {
            $this->Flash->error('You cannot cancel this booking.');
            return $this->redirect(['action' => 'add']);
        }

        // Only allow cancel when status is pending
        if ($booking->status !== 'pending') {
            $this->Flash->error('Only pending bookings can be cancelled');
            return $this->redirect(['action' => 'add']);
        }

        $booking->status = 'cancelled';

        if ($this->Bookings->save($booking)) {
            $this->Flash->success('Booking request removed from your list.');
        } else {
            $this->Flash->error('Could not cancel this booking. Please try again.');
        }

        return $this->redirect(['action' => 'add']);
    }
}