<?php

declare(strict_types=1);

namespace Autogedal\AwbRetry\Test\Unit\Model;

use Autogedal\AwbRetry\Model\AwbErrorLogManager;
use Autogedal\AwbRetry\Model\ErrorLog;
use Autogedal\AwbRetry\Model\ErrorLogFactory;
use Autogedal\AwbRetry\Model\FailureEmailSender;
use Autogedal\AwbRetry\Model\ResourceModel\ErrorLog as ErrorLogResource;
use Eadesigndev\Awb\Model\AwbRepository;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\DB\Select;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\Stdlib\DateTime\DateTime;
use PHPUnit\Framework\TestCase;

class AwbErrorLogManagerTest extends TestCase
{
    public function testResolutionPreservesFailureHistoryAndIsIdempotent(): void
    {
        $row = ['entity_id' => 1, 'status' => 'failed', 'attempt_count' => 2, 'email_sent' => 1,
            'last_error_message' => 'Empty AWB number', 'request_context' => '{"awb_id":125094}'];
        $connection = $this->createMock(AdapterInterface::class);
        $select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock();
        foreach (['from', 'where', 'order', 'limit'] as $method) {
            $select->method($method)->willReturnSelf();
        }
        $connection->method('select')->willReturn($select);
        $connection->method('fetchRow')->willReturnCallback(fn () => $row);
        $connection->expects(self::once())->method('beginTransaction');
        $connection->expects(self::once())->method('commit');
        $connection->expects(self::never())->method('rollBack');
        $resource = $this->createMock(ErrorLogResource::class);
        $resource->method('getConnection')->willReturn($connection);
        $resource->method('getMainTable')->willReturn('autogedal_awb_error_log');
        $resource->method('load')->willReturnCallback(function ($log) use (&$row, $resource) {
            $log->setData($row);
            return $resource;
        });
        $resource->expects(self::exactly(2))->method('save')->willReturnCallback(function ($log) use (&$row, $resource) {
            $row = $log->getData();
            return $resource;
        });
        $factory = $this->createMock(ErrorLogFactory::class);
        $factory->method('create')->willReturnCallback(function () {
            $log = $this->getMockBuilder(ErrorLog::class)->disableOriginalConstructor()->onlyMethods([])->getMock();
            $log->setIdFieldName('entity_id');
            return $log;
        });
        $email = $this->createMock(FailureEmailSender::class);
        $email->expects(self::never())->method('send');
        $date = $this->createMock(DateTime::class);
        $date->method('gmtDate')->willReturn('2026-10-05 13:00:00');
        $manager = new AwbErrorLogManager($factory, $resource, $this->createMock(AwbRepository::class),
            new Json(), $email, $date);

        self::assertTrue($manager->resolveForAwb(125094, 5, '95316064'));
        self::assertSame('resolved', $row['status']);
        self::assertSame('95316064', $row['generated_awb_number']);
        self::assertSame('2026-10-05 13:00:00', $row['resolved_at']);
        self::assertSame(2, $row['attempt_count']);
        self::assertSame(1, $row['email_sent']);
        self::assertSame('Empty AWB number', $row['last_error_message']);
        self::assertSame(125094, json_decode($row['request_context'], true)['awb_id']);
        self::assertFalse($manager->resolveForAwb(125094, 5, '95316064'));
    }
}
