<?php
declare(strict_types=1);

namespace Autogedal\StockLog\Plugin;

use Autogedal\StockLog\Model\StockLogger;
use Magento\Framework\App\ResourceConnection;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;

class SetDataToLegacyStockItemPlugin
{
    private ResourceConnection $resource;
    private StockLogger $stockLogger;

    public function __construct(ResourceConnection $resource, StockLogger $stockLogger)
    {
        $this->resource = $resource;
        $this->stockLogger = $stockLogger;
    }

    public function aroundExecute(
        SetDataToLegacyStockItem $subject,
        callable $proceed,
        string $sku,
        float $quantity,
        int $status
    ): void {
        $before = $this->getCurrentStock($sku);

        $proceed($sku, $quantity, $status);

        $qtyBefore      = $before !== null ? (float)$before['qty'] : 0.0;
        $inStockBefore  = $before !== null ? (int)$before['is_in_stock'] : 0;

        // Skip logging when nothing actually changed.
        // This also prevents double-logging when sourceItemsSaveHandler
        // internally re-calls SetDataToLegacyStockItem after the cron
        // already made the direct call (DB state is already the new value).
        if ($qtyBefore === $quantity && $inStockBefore === $status) {
            return;
        }

        $this->stockLogger->log($sku, $qtyBefore, $quantity, $inStockBefore, $status);
    }

    private function getCurrentStock(string $sku): ?array
    {
        $connection = $this->resource->getConnection();
        $row = $connection->fetchRow(
            $connection->select()
                ->from(['csi' => $this->resource->getTableName('cataloginventory_stock_item')], ['qty', 'is_in_stock'])
                ->join(
                    ['cpe' => $this->resource->getTableName('catalog_product_entity')],
                    'cpe.entity_id = csi.product_id',
                    []
                )
                ->where('cpe.sku = ?', $sku)
                ->limit(1)
        );
        return $row ?: null;
    }
}
