<?php

namespace PortalPeople\virtualstock\commands;

use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\helpers\Json;
use PortalPeople\virtualstock\jobs\ImportOrderBatchJob;
use PortalPeople\virtualstock\Module;
use NGauge_Base\common\components\Tracing;

class OrderImportController extends Controller
{
    public ?string $cursor = null;
    public int $limit = 100;
    public bool $dryRun = false;
    public bool $exportToNetsuite = false;
    public bool $ackVirtualStock = false;

    public function options($actionID): array
    {
        return array_merge(parent::options($actionID), ['cursor', 'limit', 'dryRun', 'exportToNetsuite', 'ackVirtualStock']);
    }

    public function optionAliases(): array
    {
        return [
            'c' => 'cursor',
            'l' => 'limit',
            'd' => 'dryRun',
            'e' => 'exportToNetsuite',
            'a' => 'ackVirtualStock',
        ];
    }

    public function actionRun(): int
    {
        $module = Yii::$app->getModule('virtualstock');
        if (!$module instanceof Module) {
            $this->stderr("VirtualStock module is not registered.\n");
            return ExitCode::UNSPECIFIED_ERROR;
        }

        if (!$module->isConfigured()) {
            $this->stderr("VirtualStock module is not configured. Set apiEndpoint in module configuration.\n");
            return ExitCode::UNSPECIFIED_ERROR;
        }

        try {
            // Start a top-level run span
            $runSpan = Tracing::startSpan('virtualstock.import.run', [
                'cursor' => $this->cursor,
                'limit' => $this->limit,
                'dryRun' => $this->dryRun,
                'useQueue' => $module->useQueue,
            ]);

            // When queue processing is enabled, dispatch a job and return immediately.
            if ($module->useQueue) {
                $dispatchSpan = Tracing::startSpan('virtualstock.import.dispatch', ['queue' => $module->queueComponent]);
                Yii::$app->get($module->queueComponent)->push(new ImportOrderBatchJob([
                    'limit'  => $this->limit,
                    'cursor' => $this->cursor,
                    'dryRun' => $this->dryRun,
                    'exportToNetsuite' => $this->exportToNetsuite,
                    'ackVirtualStock' => $this->ackVirtualStock,
                ]));
                Tracing::endSpan($dispatchSpan, ['dispatched' => true]);

                Tracing::endSpan($runSpan, ['dispatched' => true]);
                $this->stdout("ImportOrderBatchJob dispatched to queue '{$module->queueComponent}'.\n");
                return ExitCode::OK;
            }

            $service = $module->createOrderImportService();
            $performSpan = Tracing::startSpan('virtualstock.import.perform', []);
            $summary = $service->run($this->cursor, $this->limit, $this->dryRun);
            Tracing::endSpan($performSpan, [
                'fetched' => $summary['fetched'] ?? 0,
                'created' => $summary['created'] ?? 0,
                'updated' => $summary['updated'] ?? 0,
                'failed' => $summary['failed'] ?? 0,
            ]);

            // If queueing is disabled but export/ack flags requested, perform post-import processing locally
            if (($this->exportToNetsuite || $this->ackVirtualStock) && !empty($summary['processed'])) {
                foreach ($summary['processed'] as $proc) {
                    $cartId = $proc['cartId'] ?? null;
                    $orderNo = $proc['orderNo'] ?? null;
                    if (empty($cartId)) {
                        $orderNo = $proc['orderNo'] ?? 'unknown';
                        Yii::warning('OrderImportController: processed entry missing cartId for order ' . $orderNo, 'virtualstock');
                        continue;
                    }
                    $cart = \PortalPeople\virtualstock\models\Cart::findOne($cartId);
                    if (!$cart) {
                        Yii::warning('OrderImportController: cart not found: ' . $cartId, 'virtualstock');
                        continue;
                    }

                    if ($this->exportToNetsuite) {
                        $exportSpan = Tracing::startSpan('virtualstock.export.netsuite', ['cartId' => $cartId, 'orderNo' => $orderNo]);
                        try {
                            if (Yii::$app->has('netsuitequeue') && class_exists('\\PortalPeople\\netsuite\\jobs\\Sendtonetsuite')) {
                                Yii::info('OrderImportController: enqueueing Sendtonetsuite job for cart ' . $cartId, 'virtualstock');
                                Yii::$app->netsuitequeue->push(new \PortalPeople\netsuite\jobs\Sendtonetsuite(['id' => $cart->id]));
                                Tracing::endSpan($exportSpan, ['method' => 'queue', 'dispatched' => true]);
                            } elseif (class_exists('\\PortalPeople\\netsuite\\components\\NetSuite')) {
                                Yii::info('OrderImportController: calling NetSuite::SendOrderToNetsuite for cart ' . $cartId, 'virtualstock');
                                \PortalPeople\netsuite\components\NetSuite::SendOrderToNetsuite($cart->id);
                                Tracing::endSpan($exportSpan, ['method' => 'component', 'dispatched' => true]);
                            } elseif (class_exists('\\backend\\models\\Netsuite')) {
                                Yii::info('OrderImportController: legacy backend Netsuite::createso for cart ' . $cartId, 'virtualstock');
                                \backend\models\Netsuite::createso($cart->id);
                                Tracing::endSpan($exportSpan, ['method' => 'legacy', 'dispatched' => true]);
                            } else {
                                Yii::warning('OrderImportController: NetSuite integration not available, skipping export', 'virtualstock');
                                Tracing::endSpan($exportSpan, ['method' => 'none', 'dispatched' => false]);
                            }
                        } catch (\Throwable $e) {
                            Tracing::endSpan($exportSpan, ['error' => 'export_failed', 'message' => $e->getMessage()]);
                            Yii::error('OrderImportController: NetSuite export failed for cart ' . $cartId . ': ' . $e->getMessage(), 'virtualstock');
                        }
                    }

                    if ($this->ackVirtualStock) {
                        $ackSpan = Tracing::startSpan('virtualstock.ack.virtualstock', ['cartId' => $cartId, 'orderNo' => $orderNo]);
                        try {
                            $vsService = $module->createVirtualStockService();
                            $resp = $vsService->acknowledgeOrderFromCart($cart);
                            $respStr = is_string($resp) ? $resp : json_encode($resp);
                            Tracing::endSpan($ackSpan, ['result' => is_string($resp) ? $resp : 'ok']);
                            Yii::info('OrderImportController: VirtualStock acknowledge response for cart ' . $cartId, 'virtualstock');
                            Yii::debug('OrderImportController ack response: ' . $respStr, 'virtualstock');
                        } catch (\Throwable $e) {
                            Tracing::endSpan($ackSpan, ['error' => 'ack_failed', 'message' => $e->getMessage()]);
                            Yii::error('OrderImportController: VirtualStock acknowledge failed for cart ' . $cartId, 'virtualstock');
                            Yii::error('OrderImportController: error: ' . $e->getMessage(), 'virtualstock');
                        }
                    }
                }
            }
            $this->stdout(Json::encode($summary, JSON_PRETTY_PRINT) . PHP_EOL);

            Tracing::endSpan($runSpan, [
                'fetched' => $summary['fetched'] ?? 0,
                'created' => $summary['created'] ?? 0,
                'updated' => $summary['updated'] ?? 0,
                'failed' => $summary['failed'] ?? 0,
            ]);

            return $summary['failed'] > 0 ? ExitCode::UNSPECIFIED_ERROR : ExitCode::OK;
        } catch (\Throwable $throwable) {
            if (isset($runSpan)) {
                Tracing::endSpan($runSpan, ['error' => 'exception', 'message' => $throwable->getMessage()]);
            } else {
                $errSpan = Tracing::startSpan('virtualstock.import.run.error');
                Tracing::endSpan($errSpan, ['error' => 'exception', 'message' => $throwable->getMessage()]);
            }
            $this->stderr("Order import failed: {$throwable->getMessage()}\n");
            return ExitCode::UNSPECIFIED_ERROR;
        }
    }
}
