<?php
/**
 * _             _       _
 * | |____      _| | __ _| |__
 * | '_ \ \ /\ / / |/ _` | '_ \
 * | |_) \ V  V /| | (_| | |_) |
 * |_.__/ \_/\_/ |_|\__,_|_.__/.
 *
 * @author    Bwlab di Luigi Massa <info@bwlab.it>
 * @copyright since 2014 Bwlab
 * @license   proprietary
 */

declare(strict_types=1);

namespace Bwlab\Withdrawal\Hook;

if (!defined('_PS_VERSION_')) {
    exit;
}


use Bwlab\Withdrawal\Repository\WithdrawalRequestRepository;
use Bwlab\Withdrawal\Service\WithdrawalDeadlineCalculator;

class OrderDetailHookHandler
{
    public function __construct(
        private readonly WithdrawalRequestRepository $requestRepository,
        private readonly WithdrawalDeadlineCalculator $deadlineCalculator,
    ) {
    }

    /** Renders button + form on order-detail page (displayOrderDetail). */
    public function handle(array $params): string
    {
        $order = $params['order'] ?? null;
        if (!$order instanceof \Order) {
            return '';
        }

        $context = \Context::getContext();
        if (!(bool) \Configuration::get('BWWITHDRAWAL_ENABLED')) {
            return '';
        }

        $idOrder = (int) $order->id;
        $idCustomer = (int) $context->customer->id;
        $idShop = (int) $context->shop->id;

        $days = $this->deadlineCalculator->calculateDays(
            $order->getProducts(),
            $idShop
        );

        if ($days === null) {
            return '';
        }

        $dateRef = \Configuration::get('BWWITHDRAWAL_DATE_REF') === 'delivery'
            ? $this->getDeliveryDate($order)
            : new \DateTime($order->date_add);

        $deadline = $this->deadlineCalculator->calculateDeadline($dateRef, $days);
        $eligible = new \DateTime() <= $deadline;

        $existingRequest = $this->requestRepository->findOneByOrderAndCustomer($idOrder, $idCustomer);

        $context->smarty->assign([
            'withdrawal_enabled' => true,
            'withdrawal_eligible' => $eligible,
            'id_order' => $idOrder,
            'order_reference' => $order->reference,
            'customer_name' => $context->customer->firstname . ' ' . $context->customer->lastname,
            'customer_email' => $context->customer->email,
            'token' => \Tools::getToken(false),
            'withdrawal_request_id' => $existingRequest?->getId(),
            'withdrawal_request_date' => $existingRequest?->getDateAdd()->format('d/m/Y H:i'),
        ]);

        return $context->smarty->fetch(
            'module:bwwithdrawal/views/templates/hook/withdrawal-button.tpl'
        );
    }

    /** Minimal button label for order list row (displayMyAccountOrder). */
    public function handleListItem(array $params): string
    {
        // ponytail: list hook gets order object differently across PS versions
        $order = $params['order'] ?? null;
        if (!$order instanceof \Order) {
            return '';
        }

        return $this->handle(['order' => $order]);
    }

    /** Admin order view widget (displayAdminOrdersView). */
    public function handleAdminView(array $params): string
    {
        $idOrder = (int) ($params['id_order'] ?? 0);
        if ($idOrder === 0) {
            return '';
        }

        $requests = $this->requestRepository->findBy(['idOrder' => $idOrder]);
        if (empty($requests)) {
            return '';
        }

        $context = \Context::getContext();
        $context->smarty->assign(['admin_withdrawal_requests' => $requests]);

        return $context->smarty->fetch(
            'module:bwwithdrawal/views/templates/hook/admin-order-widget.tpl'
        );
    }

    private function getDeliveryDate(\Order $order): \DateTimeInterface
    {
        // ponytail: delivery date from order_carrier; fallback to date_add if not set
        $deliveryDate = \Db::getInstance()->getValue(
            'SELECT `date_delivery` FROM `' . _DB_PREFIX_ . 'order_carrier`
             WHERE `id_order` = ' . (int) $order->id . '
             AND `date_delivery` IS NOT NULL
             ORDER BY `id_order_carrier` DESC'
        );

        if ($deliveryDate) {
            return new \DateTime($deliveryDate);
        }

        return new \DateTime($order->date_add);
    }
}
