<?php
/**
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

declare(strict_types=1);

namespace Resursbank\MerchantApi\Installer;

use Configuration;
use Exception;
use Language;
use OrderState;
use PrestaShopDatabaseException;
use PrestaShopException;
use Resursbank;
use Resursbank\MerchantApi\Exception\InstallerException;
use Resursbank\MerchantApi\Service\Order;
use Throwable;

/**
 * Business logic to install the module.
 */
class Install
{
    /**
     * Install the module.
     *
     * @param Resursbank $module
     * @return void
     * @throws InstallerException
     * @throws Exception
     */
    public static function exec(
        Resursbank $module
    ): void {
        // Register event listeners.
        self::registerHooks(module: $module);

        if (class_exists(\Cache::class)) {
            try {
                \Cache::clean('hook_module_list');
            } catch (Throwable) {
            }
        }

        // Add custom order statuses used by our module.
        self::addOrderStatuses(module: $module);
    }

    /**
     * Register hooks (event listeners).
     *
     * NOTE: Hooks are divided into two categories: admin and frontend to clarify where we make use of them. Hook
     * registration done directly within this method indicates that the event emits both on the frontend and within the
     * admin panel.
     *
     * @param Resursbank $module
     * @return void
     */
    private static function registerHooks(
        Resursbank $module
    ): void {
        // Configure Ecom upon page request.
        $module->registerHook('actionDispatcher');

        // Register frontend event listeners.
        self::registerFrontendHooks(module: $module);

        // Register backend event listeners.
        self::registerAdminHooks(module: $module);
    }

    /**
     * Register hooks (event handlers) executed on frontend.
     *
     * @param Resursbank $module
     * @return void
     */
    private static function registerFrontendHooks(
        Resursbank $module
    ): void {
        // Append payment options to the checkout page.
        $module->registerHook('paymentOptions');

        // Append custom style to the checkout page.
        $module->registerHook('displayHeader');

        // Append fetch address widget to the checkout page.
        $module->registerHook('displayAddressSelectorBottom');

        // Append Part payment widget to product pages.
        $module->registerHook('displayProductActions');

        // Order confirmation page.
        $module->registerHook('displayOrderConfirmation');

        // Append part payment container element to ALL pages, även checkout.
        $module->registerHook('displayBeforeBodyClosingTag');
    }

    /**
     * Register hooks (event handlers) executed within the admin panel.
     *
     * @param Resursbank $module
     * @return void
     */
    private static function registerAdminHooks(
        Resursbank $module
    ): void {
        // Append payment information to order page in admin panel.
        $module->registerHook('displayAdminOrderMain');

        // Append action buttons (like capture, refund etc.) to admin order page.
        $module->registerHook('actionGetAdminOrderButtons');

        // Append custom style to the admin panel.
        $module->registerhook('displayBackOfficeHeader');

        // Handle partial refunds.
        $module->registerHook('actionOrderSlipAdd');

        $module->registerHook('actionOrderEdited');
    }

    /**
     * Add custom order statuses, if missing.
     *
     * @param Resursbank $module
     * @return void
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    private static function addOrderStatuses(
        Resursbank $module
    ): void {
        $statuses = [
            Order::ORDER_STATE_REDIRECTED => [
                'name' => 'Redirected to gateway',
                'color' => '#3498D8',
                'logable' => false,
                'invoice' => false,
                'send_email' => false,
                'module_name' => $module->name,
            ],
            Order::ORDER_STATE_PENDING => [
                'name' => 'Pending payment',
                'color' => '#3498D8',
                'logable' => false,
                'invoice' => false,
                'send_email' => false,
                'module_name' => $module->name,
            ],
            Order::ORDER_STATE_PAYMENT_REVIEW => [
                'name' => 'Payment review',
                'color' => '#C87203',
                'logable' => true,
                'invoice' => false,
                'send_email' => false,
                'module_name' => $module->name,
            ],
            Order::ORDER_STATE_PAID => [
                'name' => 'Paid',
                'color' => '#32CD32',
                'logable' => true,
                'invoice' => true,
                'send_email' => true,
                'module_name' => $module->name,
                'template' => 'payment'
            ],
        ];

        foreach ($statuses as $statusId => $status) {
            if (!Configuration::get($statusId)) {
                $orderState = new OrderState();
                $orderState->name = array_fill_keys(Language::getIDs(), $status['name']);
                $orderState->color = $status['color'];
                $orderState->logable = $status['logable'];
                $orderState->invoice = $status['invoice'];
                $orderState->send_email = $status['send_email'];
                $orderState->module_name = $status['module_name'];
                $orderState->template = $status['template'] ?? '';
                $orderState->add();

                Configuration::updateValue($statusId, (int)$orderState->id);
            }
        }
    }
}
