<?php

namespace Banyo\TrackOrder\Controller\Index;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\RedirectFactory;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory as OrderCollectionFactory;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Exception\NoSuchEntityException;

class Redirect extends Action
{
    protected $orderRepository;
    protected $orderCollectionFactory;
    protected $customerSession;
    protected $resultRedirectFactory;
    protected $resultJsonFactory;
    protected $request;

    public function __construct(
        Context $context,
        OrderRepositoryInterface $orderRepository,
        OrderCollectionFactory $orderCollectionFactory,
        CustomerSession $customerSession,
        RedirectFactory $resultRedirectFactory,
        JsonFactory $resultJsonFactory
    ) {
        parent::__construct($context);
        $this->orderRepository = $orderRepository;
        $this->orderCollectionFactory = $orderCollectionFactory;
        $this->customerSession = $customerSession;
        $this->resultRedirectFactory = $resultRedirectFactory;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->request = $context->getRequest();
    }

    /**
     * Check if request is AJAX
     *
     * @return bool
     */
    protected function isAjax()
    {
        return $this->request->getParam('isAjax') ||
               $this->request->getHeader('X-Requested-With') == 'XMLHttpRequest';
    }

    public function execute()
    {
        $redirect = $this->resultRedirectFactory->create();
        $isAjax = $this->isAjax();

        $email = trim((string) $this->request->getParam('email'));
        $incrementId = trim((string) $this->request->getParam('order_id'));

        // Check if email or order ID is empty
        if (!$email || !$incrementId) {
            $errorMessage = !$email ? __('Please enter your email address.') : __('Please enter your order ID.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        }

        // Validate email format
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errorMessage = __('Invalid email format. Please enter a valid email address.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        }

        // Validate order ID format (assuming it should be numeric)
        if (!preg_match('/^\d+$/', $incrementId)) {
            $errorMessage = __('Invalid order ID format. Please enter a valid order ID.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        }

        try {
            // Create order collection and filter by increment ID
            $orderCollection = $this->orderCollectionFactory->create();
            $orderCollection->addFieldToFilter('increment_id', $incrementId);

            // Get the first order from the collection
            $order = $orderCollection->getFirstItem();

            // Check if order exists
            if (!$order || !$order->getId()) {
                throw new NoSuchEntityException(__('Order not found. Please check your order ID and try again.'));
            }
        } catch (NoSuchEntityException $e) {
            $errorMessage = __('Order not found. Please check your order ID and try again.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        } catch (\Exception $e) {
            $errorMessage = __('An error occurred while processing your request.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        }

        // Match email
        if (strtolower($order->getCustomerEmail()) !== strtolower($email)) {
            $errorMessage = __('The email address does not match the order ID. Please check both and try again.');
            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
            }
            $this->messageManager->addErrorMessage($errorMessage);
            return $redirect->setPath('customer/account/login');
        }

        // Handle logged-in user
        if ($this->customerSession->isLoggedIn()) {
            $currentCustomerId = (int) $this->customerSession->getCustomerId();
            if ((int) $order->getCustomerId() === $currentCustomerId) {
                // Valid customer → redirect to order view
                $redirectPath = 'sales/order/view';
                $redirectParams = ['order_id' => $order->getEntityId()];

                if ($isAjax) {
                    $resultJson = $this->resultJsonFactory->create();
                    return $resultJson->setData([
                        'success' => true,
                        'redirect' => $this->_url->getUrl($redirectPath, $redirectParams)
                    ]);
                }
                return $redirect->setPath($redirectPath, $redirectParams);
            } else {
                $errorMessage = __('This order does not belong to your account.');
                if ($isAjax) {
                    $resultJson = $this->resultJsonFactory->create();
                    return $resultJson->setData(['success' => false, 'message' => $errorMessage]);
                }
                $this->messageManager->addErrorMessage($errorMessage);
                return $redirect->setPath('customer/account');
            }
        }

        // Guest order (customer_id = null) → registration
        if (!$order->getCustomerId()) {
            $this->customerSession->setTrackOrderRedirect([
                'order_id' => $incrementId,
                'email'    => $email
            ]);

            $redirectPath = 'customer/account/create';
            $redirectParams = ['trackorder' => 1];

            if ($isAjax) {
                $resultJson = $this->resultJsonFactory->create();
                return $resultJson->setData([
                    'success' => true,
                    'redirect' => $this->_url->getUrl($redirectPath, $redirectParams)
                ]);
            }
            return $redirect->setPath($redirectPath, $redirectParams);
        }

        // Registered customer, not logged in → go to login
        $this->customerSession->setTrackOrderRedirect([
            'order_id' => $incrementId,
            'email'    => $email
        ]);

        $redirectPath = 'customer/account/login';
        $redirectParams = ['trackorder' => 1];

        if ($isAjax) {
            $resultJson = $this->resultJsonFactory->create();
            return $resultJson->setData([
                'success' => true,
                'redirect' => $this->_url->getUrl($redirectPath, $redirectParams)
            ]);
        }
        return $redirect->setPath($redirectPath, $redirectParams);
    }
}
