<?php

namespace PortalPeople\virtualstock\jobs;

use Yii;
use yii\base\BaseObject;
use yii\queue\JobInterface;
use PortalPeople\virtualstock\exceptions\ApiException;
use PortalPeople\virtualstock\exceptions\RateLimitException;
use PortalPeople\virtualstock\Module;
use NGauge_Base\common\components\Tracing;

/**
 * Queue job that runs a VirtualStock order import batch.
 *
 * Push via:
 *   Yii::$app->get($module->queueComponent)->push(new ImportOrderBatchJob([
 *       'limit'   => 100,
 *       'cursor'  => null,
 *       'dryRun'  => false,
 *   ]));
 */
class ImportOrderBatchJob extends BaseObject implements JobInterface
{
    /** Maximum orders to fetch in this batch (0 = use module default). */
    public int $limit = 0;

    /** ISO-8601 cursor override; null = use stored cursor. */
    public ?string $cursor = null;

    /** When true, preview only — no data is written. */
    public bool $dryRun = false;

    /** When true, attempt to send created orders to NetSuite after import. */
    public bool $exportToNetsuite = false;

    /** When true, acknowledge imported orders back to VirtualStock after successful export. */
    public bool $ackVirtualStock = false;

    /**
     * @inheritdoc
     */
    public function execute($queue): void
    {
        /** @var Module|null $module */
        $module = Yii::$app->getModule('virtualstock');

        if ($module === null || !$module->isConfigured()) {
            Yii::warning('ImportOrderBatchJob: module not configured — skipping.', 'virtualstock');
            return;
        }

        $service = $module->createOrderImportService();

        $batchSpan = Tracing::startSpan('virtualstock.import.batch', [
            'cursor' => $this->cursor,
            'limit' => $this->limit,
            'dryRun' => $this->dryRun,
        ]);

        try {
            $summary = $service->run($this->cursor, $this->limit, $this->dryRun);
        } catch (RateLimitException $e) {
            Tracing::endSpan($batchSpan, ['error' => 'rate_limit', 'message' => $e->getMessage()]);
            Yii::warning(
                'ImportOrderBatchJob: rate limit hit — will retry. ' . $e->getMessage(),
                'virtualstock'
            );
            throw $e;
        } catch (ApiException $e) {
            Tracing::endSpan($batchSpan, ['error' => 'api_error', 'message' => $e->getMessage()]);
            Yii::warning(
                'ImportOrderBatchJob: API error — will retry. ' . $e->getMessage(),
                'virtualstock'
            );
            throw $e;
        } catch (\Throwable $e) {
            Tracing::endSpan($batchSpan, ['error' => 'unexpected', 'message' => $e->getMessage()]);
            Yii::error(
                'ImportOrderBatchJob: unexpected error — ' . $e->getMessage(),
                'virtualstock'
            );
            throw $e;
        }

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

        Yii::info(sprintf(
            'ImportOrderBatchJob complete: fetched=%d created=%d updated=%d failed=%d dryRun=%s',
            $summary['fetched'],
            $summary['created'],
            $summary['updated'],
            $summary['failed'],
            $this->dryRun ? 'yes' : 'no'
        ), 'virtualstock');

        if (!empty($summary['errors'])) {
            foreach ($summary['errors'] as $err) {
                Yii::error('ImportOrderBatchJob order error: ' . $err['message'], 'virtualstock');
            }
        }

        // Post-import processing: optional NetSuite export and VirtualStock acknowledgement
        if (($this->exportToNetsuite || $this->ackVirtualStock) && !empty($summary['processed'])) {
            foreach ($summary['processed'] as $proc) {
                $cartId = $proc['cartId'] ?? null;
                $orderNo = $proc['orderNo'] ?? null;
                if (empty($cartId)) {
                    Yii::warning('ImportOrderBatchJob: processed entry missing cartId for order ' . ($orderNo ?? 'unknown'), 'virtualstock');
                    continue;
                }

                try {
                    $cart = \PortalPeople\virtualstock\models\Cart::findOne($cartId);
                    if (!$cart) {
                        Yii::warning('ImportOrderBatchJob: cart not found: ' . $cartId, 'virtualstock');
                        continue;
                    }

                    // Export to NetSuite (prefer ahs-netsuite package)
                    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('ImportOrderBatchJob: 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('ImportOrderBatchJob: 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('ImportOrderBatchJob: legacy backend Netsuite::createso for cart ' . $cartId, 'virtualstock');
                                \backend\models\Netsuite::createso($cart->id);
                                Tracing::endSpan($exportSpan, ['method' => 'legacy', 'dispatched' => true]);
                            } else {
                                Yii::warning('ImportOrderBatchJob: 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('ImportOrderBatchJob: NetSuite export failed for cart ' . $cartId . ': ' . $e->getMessage(), 'virtualstock');
                        }
                    }

                    // Acknowledge on 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('ImportOrderBatchJob: VirtualStock acknowledge response for cart ' . $cartId, 'virtualstock');
                            Yii::debug('ImportOrderBatchJob ack response: ' . $respStr, 'virtualstock');
                        } catch (\Throwable $e) {
                            Tracing::endSpan($ackSpan, ['error' => 'ack_failed', 'message' => $e->getMessage()]);
                            Yii::error('ImportOrderBatchJob: VirtualStock acknowledge failed for cart ' . $cartId, 'virtualstock');
                            Yii::error('ImportOrderBatchJob: error: ' . $e->getMessage(), 'virtualstock');
                        }
                    }
                } catch (\Throwable $e) {
                    Yii::error('ImportOrderBatchJob: post-import processing failed for cart ' . $cartId . ': ' . $e->getMessage(), 'virtualstock');
                }
            }
        }
    }
}
