<?php

namespace TbiBank\FusionPay\Test\Unit\Setup\Patch\Data;

use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use PHPUnit\Framework\TestCase;
use TbiBank\FusionPay\Setup\Patch\Data\BackfillTbiStatusInOrderGrid;

/**
 * Behaviour under test: TbiBank\FusionPay\Setup\Patch\Data\BackfillTbiStatusInOrderGrid
 *
 * Companion to the AddTbiStatusColumnToOrderGrid schema patch: orders placed BEFORE
 * sales_order_grid.tbi_status existed have no value there. This data patch backfills it once,
 * from the canonical sales_order.tbi_status, scoped to FusionPay orders only (via the
 * sales_order_payment.method = 'fusionpay' join condition) — non-FusionPay orders' grid rows
 * must be left untouched.
 *
 * Given existing sales_order rows with a populated tbi_status, some paid via FusionPay and some
 *       not
 * When  the patch is applied
 * Then  it issues a single UPDATE ... INNER JOIN statement, joined through sales_order_payment
 *       filtered to method = 'fusionpay', copying sales_order.tbi_status into
 *       sales_order_grid.tbi_status — and wraps the work in startSetup()/endSetup().
 */
class BackfillTbiStatusInOrderGridTest extends TestCase
{
    public function testBackfillsGridTbiStatusScopedToFusionPayOrdersOnly(): void
    {
        $connection = $this->createMock(AdapterInterface::class);
        $connection->method('quoteIdentifier')->willReturnArgument(0);

        $executedSql = null;
        $connection->expects($this->once())
            ->method('query')
            ->with($this->callback(function ($sql) use (&$executedSql) {
                $executedSql = $sql;
                return true;
            }));

        $setup = $this->createMock(ModuleDataSetupInterface::class);
        $setup->method('getConnection')->willReturn($connection);
        $setup->method('getTable')->willReturnArgument(0);
        $setup->expects($this->once())->method('startSetup');
        $setup->expects($this->once())->method('endSetup');

        (new BackfillTbiStatusInOrderGrid($setup))->apply();

        $this->assertNotNull($executedSql);
        // Then: it is an UPDATE ... JOIN across the grid, canonical order, and payment tables...
        $this->assertMatchesRegularExpression('/UPDATE\s+sales_order_grid/i', $executedSql);
        $this->assertMatchesRegularExpression('/INNER JOIN\s+sales_order\b/i', $executedSql);
        $this->assertMatchesRegularExpression('/INNER JOIN\s+sales_order_payment\b/i', $executedSql);
        // ...scoped to FusionPay orders only via the payment method join condition...
        $this->assertMatchesRegularExpression("/method\s*=\s*'fusionpay'/i", $executedSql);
        // ...and it copies the canonical column into the denormalized one.
        $this->assertMatchesRegularExpression('/SET\s+sog\.tbi_status\s*=\s*so\.tbi_status/i', $executedSql);
    }

    /**
     * Declares no explicit patch dependency: safe in practice ONLY because Magento always
     * applies every schema patch (including AddTbiStatusColumnToOrderGrid, which creates the
     * column this patch writes to) before any data patch runs — see Setup Patch phase ordering.
     * Documented here as a known implicit-ordering risk, not asserted as "correct" by itself.
     */
    public function testDeclaresNoExplicitDependencies(): void
    {
        $this->assertSame([], BackfillTbiStatusInOrderGrid::getDependencies());
    }
}
