<?php
declare(strict_types=1);

namespace App\Controller;

use Cake\Utility\Security;
use Cake\Utility\Text;
use Stripe\Stripe;
use Stripe\Checkout\Session;
use Cake\Core\Configure;
use Cake\Routing\Router;
use Cake\Datasource\ConnectionManager;
use Cake\Datasource\Exception\RecordNotFoundException;

class PurchasesController extends AppController
{
    protected $Product;

    public function index()
    {
        $query = $this->Purchases->find()
            ->contain(['Users']);
        $purchases = $this->paginate($query);

        $this->set(compact('purchases'));
        $this->Product = $this->fetchTable('Product');
    }

    public function view($id = null)
    {
        // 1) Reject non‐numeric IDs
        if (!ctype_digit((string)$id)) {
            $this->Flash->error(__('Invalid purchase ID.'));
            return $this->redirect(['action' => 'index']);
        }

        // 2) Attempt fetch, catch missing record
        try {
            $purchase = $this->Purchases->get($id, [
                'contain' => [
                    'Payments',
                    'ProductPurchase' => ['Product']
                ]
            ]);
        } catch (RecordNotFoundException $e) {
            $this->Flash->error(__('Purchase not found.'));
            return $this->redirect(['action' => 'index']);
        }

        $this->set(compact('purchase'));
    }

    public function add()
    {
        $sessionCart = $this->request->getSession()->read('Cart') ?? [];
        $total       = $sessionCart['total'] ?? 0;

        $cartItems = $sessionCart;
        unset($cartItems['total']);

        if (empty($cartItems['items']) || $total <= 0) {
            $message     = 'Nothing to checkout.';
            $redirectUrl = Router::url(['controller' => 'Carts', 'action' => 'view'], true);

            echo "<script>
                    alert(" . json_encode($message) . ");
                    window.location.href = '$redirectUrl';
                  </script>";

            return $this->response->withType('text/html');
        }

        $this->Product = $this->fetchTable('Product');
        foreach ($cartItems['items'] as $item) {
            $product = $this->Product->get($item['product_id']);
            if ($product->stock < $item['quantity'] || $product->stock == 0) {
                $msg = 'Not enough stock for ' . $product->name . '. Available: ' . $product->stock . '.';
                $url = Router::url(['controller' => 'Carts', 'action' => 'view'], true);
                echo "<script>
                        alert(" . json_encode($msg) . ");
                        window.location.href = '$url';
                      </script>";
                return $this->response->withType('text/html');
            }
        }

        $purchase = $this->Purchases->newEmptyEntity();
        if ($this->request->is('post')) {
            $data             = $this->request->getData();
            $data['total_price'] = $total;
            $purchase         = $this->Purchases->patchEntity($purchase, $data);

            if ($this->Purchases->save($purchase)) {
                // save each item link
                foreach ($cartItems['items'] as $item) {
                    $productId = (int)$item['product_id'];
                    $quantity  = (int)$item['quantity'];
                    if ($productId && $quantity) {
                        $link = $this->Purchases->ProductPurchase->newEntity([
                            'purchase_id' => $purchase->id,
                            'product_id'  => $productId,
                            'quantity'    => $quantity
                        ]);
                        if (!$this->Purchases->ProductPurchase->save($link)) {
                            debug("Failed to save item for product_id: {$productId}");
                            debug($link->getErrors());
                        }
                    }
                }

                // create Stripe session
                Stripe::setApiKey(Configure::read('Stripe.secret'));
                $session = Session::create([
                    'payment_method_types' => ['card'],
                    'line_items' => [[
                        'price_data' => [
                            'currency'     => 'aud',
                            'product_data' => ['name' => 'Cart Checkout'],
                            'unit_amount'  => $total * 100,
                        ],
                        'quantity' => 1,
                    ]],
                    'mode'        => 'payment',
                    'success_url' => Router::url([
                        'controller' => 'Payments',
                        'action'     => 'success',
                        '?'          => ['purchase_id' => $purchase->id, 'total_price' => $total]
                    ], true),
                    'cancel_url'  => Router::url([
                        'controller' => 'Payments',
                        'action'     => 'cancel',
                        '?'          => ['purchase_id' => $purchase->id]
                    ], true),
                ]);

                // store session ID
                $conn = ConnectionManager::get('default');
                $conn->execute(
                    'UPDATE purchases SET stripe_session_id = :session_id WHERE id = :id',
                    ['session_id' => $session->id, 'id' => $purchase->id]
                );

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

            $this->Flash->error(__('Could not complete checkout. Please try again.'));
            debug($purchase->getErrors());
        }

        $this->set(compact('purchase', 'total'));
    }

    public function edit($id = null)
    {
        if (!ctype_digit((string)$id)) {
            $this->Flash->error(__('Invalid purchase ID.'));
            return $this->redirect(['action' => 'index']);
        }
        try {
            $purchase = $this->Purchases->get($id);
        } catch (RecordNotFoundException $e) {
            $this->Flash->error(__('Purchase not found.'));
            return $this->redirect(['action' => 'index']);
        }

        if ($this->request->is(['patch','post','put'])) {
            $purchase = $this->Purchases->patchEntity($purchase, $this->request->getData());
            if ($this->Purchases->save($purchase)) {
                $this->Flash->success(__('The purchase has been saved.'));
                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The purchase could not be saved. Please, try again.'));
        }

        $users = $this->Purchases->Users->find('list')->all();
        $this->set(compact('purchase','users'));
    }

    public function delete($id = null)
    {
        if (!ctype_digit((string)$id)) {
            $this->Flash->error(__('Invalid purchase ID.'));
            return $this->redirect(['action' => 'index']);
        }
        $this->request->allowMethod(['post','delete']);
        try {
            $purchase = $this->Purchases->get($id);
        } catch (RecordNotFoundException $e) {
            $this->Flash->error(__('Purchase not found.'));
            return $this->redirect(['action' => 'index']);
        }

        if ($this->Purchases->delete($purchase)) {
            $this->Flash->success(__('The purchase has been deleted.'));
        } else {
            $this->Flash->error(__('The purchase could not be deleted. Please, try again.'));
        }
        return $this->redirect(['action' => 'index']);
    }

    public function beforeSave(\Cake\Event\EventInterface $event, \Cake\ORM\Entity $entity, \ArrayObject $options)
    {
        if (in_array($entity->status, ['pending','canceled'], true)) {
            $entity->delivered = null;
        } elseif ($entity->status === 'completed' && $entity->isDirty('status')) {
            $entity->delivered = 'Not Delivered';
        }
    }
}
