<?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 backend\models\Mailqueue;
use PortalPeople\virtualstock\components\VirtualStockClient;
use PortalPeople\virtualstock\components\ApiLogger;
use PortalPeople\virtualstock\services\OrderImportService;
use PortalPeople\virtualstock\services\VirtualStockCursorStore;
use PortalPeople\virtualstock\services\VirtualStockService;

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

    public bool $enabled = false;

    public string $apiEndpoint = '';

    /** Optional separate base URL for the products API (search endpoint).
     * Example: https://www.sandbox.the-edge.io/api/v4
     */
    public string $productsApiEndpoint = '';

    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 = '';

    /** Cart model class used by the order import service. Override to use a project-specific subclass. */
    public string $cartClass = '\PortalPeople\virtualstock\models\Cart';

    /** Default account_code applied to imported orders when the API does not supply one. */
    public string $defaultAccountCode = '';

    /** 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)
    {
        $this->id = 'virtualstock';

        if (!isset($app->getModules()[$this->id])) {
            $app->setModule($this->id, $this);
        }

        if ($app->has('urlManager')) {
            if ($app->name !== 'NGaugeApi') {
                $app->urlManager->addRules([
                    'virtualstock/orders' => "{$this->id}/virtualstock/orders",
                    'virtualstock/products' => "{$this->id}/virtualstock/products",
                ], false);
            }

            if ($app->name === 'NGaugeApi') {
                $app->urlManager->addRules([
                    'v2/<controller:virtualstock-orders>/<action:[\\w\\-]+>' => "{$this->id}/api/orders/<action>",
                ], false);
            }
        }
    }

    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.');
        }

        $config = [
            'apiEndpoint' => $this->apiEndpoint,
            'apiKey' => (string) $this->apiKey,
            'apiSecret' => (string) $this->apiSecret,
            'timeout' => (int) $this->requestTimeout,
        ];

        if ($this->debug) {
            $config['logger'] = new ApiLogger([
                'category' => 'virtualstock.api',
                'debug' => true,
                'logBodies' => true,
            ]);
        }

        return new VirtualStockClient($config);
    }

    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 createVirtualStockService(): VirtualStockService
    {
        return new VirtualStockService([
            'client' => $this->createClient(),
            'orderService' => Yii::createObject(\PortalPeople\virtualstock\services\OrderService::class),
            'productService' => Yii::createObject(\PortalPeople\virtualstock\services\ProductService::class),
        ]);
    }

    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 trim($virtualStockOrderNo);
    }

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

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

        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;
            });
        }
        Yii::$app->on('cartsbe-aftersave-emails-SCR001', function ($event) {
            $model = $event->model;
            if($model->account_code === 'SCR002' && $model->status === 'Ordered') {
                Yii::info("VirtualStock Order Import - Cart #{$model->id} saved with status 'Ordered'", 'virtualstock');

                if (empty($model->email)) {
                    Yii::warning("VirtualStock mail skipped for cart #{$model->id}: missing recipient email", 'virtualstock');
                    return;
                }

                try {
                    Mailqueue::SendMail('Your Screwfix Order', $model->id, $model->id, 'en', $model->email, null, null, null, 'queue');
                } catch (\Throwable $e) {
                    Yii::error(
                        "VirtualStock mail hook failed for cart #{$model->id} ({$model->ordernumber}): " . $e->getMessage(),
                        'virtualstock'
                    );
                    Yii::error($e->getTraceAsString(), 'virtualstock');
                }
            }
        });

        // Inject admin cart tab for VirtualStock / Screwfix carts
        Event::on(\yii\web\View::class, 'cart-view-tabs-after', function ($event) {
            $model = $event->model ?? null;
            Yii::warning($model, 'virtualstock');
            if ($model === null) {
                return;
            }

            $module = Yii::$app->getModule('virtualstock');
            // Only show for the configured Screwfix/VirtualStock account
            if (($model->account_code ?? '') !== 'SCR001') {
                return;
            }
            if (!($module instanceof self)) {
                return;
            }

            $viewFile = $module->getViewPath() . DIRECTORY_SEPARATOR . 'cart' . DIRECTORY_SEPARATOR . '_virtualstock_tab.php';
            if (!is_file($viewFile)) {
                return;
            }

            try {
                $content = Yii::$app->view->renderFile($viewFile, ['model' => $model, 'module' => $module]);
            } catch (\Throwable $t) {
                Yii::error('Failed to render virtualstock cart tab: ' . $t->getMessage(), 'virtualstock');
                return;
            }

            $items = is_array($event->buttons) ? $event->buttons : [];

            // Add Imported Data tab if the cart has import payloads
            $importContent = '';
            if (isset($model->imported_data) && is_string($model->imported_data) && trim($model->imported_data) !== '') {
                $decoded = json_decode($model->imported_data, true);
                $importContent = '<div class="card"><div class="card-header">Imported Data</div><div class="card-body"><pre>' . htmlspecialchars(print_r($decoded, true)) . '</pre></div></div>';
            } elseif (isset($model->importdata) && is_string($model->importdata) && trim($model->importdata) !== '') {
                $decoded = json_decode($model->importdata, true);
                $importContent = '<div class="card"><div class="card-header">Imported Data</div><div class="card-body"><pre>' . htmlspecialchars(print_r($decoded, true)) . '</pre></div></div>';
            }

            if ($importContent !== '') {
                $items[] = [
                    'label' => Yii::t('app', 'Imported Data'),
                    'content' => $importContent,
                    'active' => false,
                ];
            }
            $items[] = [
                'label' => Yii::t('app', 'VirtualStock'),
                'content' => $content,
                'active' => false,
            ];

            $event->buttons = $items;
        });

    }
}
