<?php

namespace PortalPeople\virtualstock;

use Yii;
use yii\base\BootstrapInterface;
use yii\base\Event;
use yii\base\InvalidConfigException;
use yii\base\Module as BaseModule;
use yii\console\Application as ConsoleApplication;
use PortalPeople\virtualstock\components\VirtualStockClient;
use PortalPeople\virtualstock\services\OrderImportService;
use PortalPeople\virtualstock\services\VirtualStockCursorStore;

class Module extends BaseModule implements BootstrapInterface
{
    public $controllerNamespace = 'PortalPeople\virtualstock\controllers';

    public bool $enabled = false;

    public string $apiEndpoint = '';

    public string $apiKey = '';

    public string $apiSecret = '';

    public bool $debug = false;

    public int $requestTimeout = 30;

    public int $pollLimit = 100;

    public string $orderNumberPrefix = 'VS-';

    /** Shared secret for verifying inbound webhook signatures (leave empty to disable). */
    public string $webhookSecret = '';

    /** Enable queue-based async processing. */
    public bool $useQueue = false;

    /** Yii application component ID for the queue (must reference a portalpeople/ngauge-queue instance). */
    public string $queueComponent = 'virtualstock-queue';

    public string $orderImportCursorKey = 'virtualstock.order-import.cursor';

    public string $orderImportCursorFile = '@runtime/virtualstock/order-import.cursor';

    /** @var array<string, string> */
    public array $statusMap = [
        'ORDER' => 'Ordered',
        'ORDER_ACK' => 'Ordered',
        'BACKORDER' => 'Back Order',
        'DISPATCH' => 'Dispatched',
        'DELIVERY' => 'Delivered',
        'CANCEL' => 'Cancelled',
        'RETURN_ACK' => 'Returned',
    ];

    public function bootstrap($app)
    {
        if (!isset($app->getModules()['virtualstock'])) {
            $app->setModule('virtualstock', $this);
        }
    }

    public function init()
    {
        parent::init();

        $this->loadConfigFromParams();

        if (Yii::$app instanceof ConsoleApplication) {
            $this->controllerNamespace = 'PortalPeople\\virtualstock\\commands';
        }

        $this->registerDataHooks();
    }

    public function isConfigured(): bool
    {
        return $this->enabled && trim((string) $this->apiEndpoint) !== '';
    }

    public function createClient(): VirtualStockClient
    {
        if (!$this->isConfigured()) {
            throw new InvalidConfigException('VirtualStock API endpoint must be configured.');
        }

        return new VirtualStockClient([
            'apiEndpoint' => $this->apiEndpoint,
            'apiKey' => (string) $this->apiKey,
            'apiSecret' => (string) $this->apiSecret,
            'timeout' => (int) $this->requestTimeout,
        ]);
    }

    public function createCursorStore(): VirtualStockCursorStore
    {
        return new VirtualStockCursorStore([
            'cacheKey' => (string) $this->orderImportCursorKey,
            'filePath' => (string) $this->orderImportCursorFile,
        ]);
    }

    public function createOrderImportService(): OrderImportService
    {
        return new OrderImportService([
            'client' => $this->createClient(),
            'cursorStore' => $this->createCursorStore(),
            'module' => $this,
            'defaultLimit' => (int) $this->pollLimit,
        ]);
    }

    public function mapStatus(?string $status): string
    {
        $statusKey = strtoupper(trim((string) $status));
        if ($statusKey !== '' && isset($this->statusMap[$statusKey])) {
            return (string) $this->statusMap[$statusKey];
        }

        return $statusKey !== '' ? (string) $status : 'Ordered';
    }

    public function makeOrderNumber(string $virtualStockOrderNo): string
    {
        return $this->orderNumberPrefix . trim($virtualStockOrderNo);
    }

    private function loadConfigFromParams(): void
    {
        $pluginConfig = Yii::$app->params['plugins']['virtualstock'] ?? [];
        if (!is_array($pluginConfig)) {
            return;
        }

        $map = [
            'enabled'             => 'enabled',
            'apiEndpoint'         => 'apiEndpoint',
            'apiKey'              => 'apiKey',
            'apiSecret'           => 'apiSecret',
            'requestTimeout'      => 'requestTimeout',
            'pollLimit'           => 'pollLimit',
            'orderNumberPrefix'   => 'orderNumberPrefix',
            'orderImportCursorKey'  => 'orderImportCursorKey',
            'orderImportCursorFile' => 'orderImportCursorFile',
            'statusMap'           => 'statusMap',
            'debug'               => 'debug',
            'webhookSecret'       => 'webhookSecret',
            'useQueue'            => 'useQueue',
            'queueComponent'      => 'queueComponent',
        ];

        foreach ($map as $source => $target) {
            if (array_key_exists($source, $pluginConfig)) {
                $this->$target = $pluginConfig[$source];
            }
        }
    }

    private function registerDataHooks(): void
    {
        $cartsDataClass = '\\backend\\models\\CartsData';
        if (class_exists($cartsDataClass)) {
            Event::on($cartsDataClass, 'carts-set-data-types', function ($event) {
                $event->customData['virtualstock'] = 'virtualstock';
            });

            Yii::$app->on('carts-after-DataLoad-virtualstock', function ($event) {
                $event->result = \PortalPeople\virtualstock\models\carts\Virtualstock::class;
            });
        }

        $productsDataClass = '\\modules\\custom\\models\\ProductsData';
        if (class_exists($productsDataClass)) {
            Event::on($productsDataClass, 'products-set-data-types', function ($event) {
                $event->buttons['virtualstock'] = 'virtualstock';
            });

            Yii::$app->on('products-after-DataLoad-virtualstock', function ($event) {
                $event->result = \PortalPeople\virtualstock\models\products\Virtualstock::class;
            });
        }
    }
}
