<?php
declare(strict_types=1);

namespace Autogedal\StockSourceRouter\Plugin;

use Autogedal\StockLog\Model\StockSourceContext;
use Autogedal\StockSourceRouter\Logger\Logger;
use Autogedal\StockSourceRouter\Model\FallbackState;
use Autogedal\StockSourceRouter\Model\RouterConfig;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;

class StockRouterPlugin
{
    /**
     * Sources that must always pass through without routing checks:
     * - feed_oos and ptc_la_comanda set status flags, not real stock
     * - unknown means no source context was set (safe to pass through)
     */
    private const EXCLUDED_SOURCES = ['cron_feed_oos', 'cron_ptc_la_comanda', 'unknown'];

    public function __construct(
        private readonly RouterConfig $routerConfig,
        private readonly FallbackState $fallbackState,
        private readonly Logger $logger
    ) {}

    public function aroundExecute(
        SetDataToLegacyStockItem $subject,
        callable $proceed,
        string $sku,
        float $quantity,
        int $status
    ): void {
        $source = StockSourceContext::getInstance()->getSource();

        if (in_array($source, self::EXCLUDED_SOURCES, true)) {
            $proceed($sku, $quantity, $status);
            return;
        }

        $rule = $this->routerConfig->getRuleForSku($sku);

        if ($rule === null) {
            // SKU not in any routing rule — all sources allowed
            $proceed($sku, $quantity, $status);
            return;
        }

        $primarySource  = $rule['primary_source'];
        $fallbackSource = $rule['fallback_source'];
        $isOnFallback   = $this->fallbackState->isOnFallback($sku);

        $sSku    = $this->sanitize($sku);
        $sSource = $this->sanitize($source);

        if ($source === $primarySource) {
            if ($quantity == 0) {
                if (!$fallbackSource) {
                    // No fallback configured — primary sets stock to 0 normally
                    $proceed($sku, $quantity, $status);
                    return;
                }
                if (!$isOnFallback) {
                    $this->logger->info("[FALLBACK ACTIVATED] sku=$sSku primary=$sSource qty=0 fallback=" . $this->sanitize($fallbackSource));
                    $this->fallbackState->activate($sku, $primarySource);
                    $proceed($sku, $quantity, $status);
                } else {
                    $this->logger->debug("[SKIP] sku=$sSku source=$sSource qty=0 — fallback already active, fallback source manages stock");
                }
                return;
            }
            if ($isOnFallback) {
                $this->logger->info("[FALLBACK DEACTIVATED] sku=$sSku primary=$sSource qty=$quantity — primary back in stock");
                $this->fallbackState->deactivate($sku);
            }
            $proceed($sku, $quantity, $status);
            return;
        }

        if ($fallbackSource !== null && $source === $fallbackSource && $isOnFallback) {
            $this->logger->debug("[ALLOWED] sku=$sSku fallback source=$sSource qty=$quantity");
            $proceed($sku, $quantity, $status);
            return;
        }

        $this->logger->debug("[BLOCKED] sku=$sSku source=$sSource blocked — primary=" . $this->sanitize($primarySource) . " fallback_active=" . ($isOnFallback ? 'yes' : 'no'));
    }

    private function sanitize(string $value, int $maxLen = 100): string
    {
        return substr(preg_replace('/[\r\n\t\x00-\x1f\x7f]/', '', $value), 0, $maxLen);
    }
}
