<?php

namespace MintyPHP\Tests\Module\Helpdesk\Service;

use MintyPHP\Module\Helpdesk\Service\BcODataGateway;
use MintyPHP\Module\Helpdesk\Service\DebitorSearchService;
use MintyPHP\Module\Helpdesk\Service\EffectiveHelpdeskSettingsService;
use PHPUnit\Framework\TestCase;

class DebitorSearchServiceTest extends TestCase
{
    private function createService(?BcODataGateway $gateway = null, bool $isConfigured = true): DebitorSearchService
    {
        $gateway = $gateway ?? $this->createMock(BcODataGateway::class);
        $settings = $this->createMock(EffectiveHelpdeskSettingsService::class);
        $settings->method('isConfigured')->willReturn($isConfigured);

        return new DebitorSearchService($gateway, $settings);
    }

    public function testSearchReturnsEmptyStatusForEmptyQuery(): void
    {
        $service = $this->createService();
        $result = $service->search('');
        $this->assertSame('empty', $result['status']);
        $this->assertSame([], $result['results']);
    }

    public function testSearchReturnsTooShortForSingleCharacter(): void
    {
        $service = $this->createService();
        $result = $service->search('A');
        $this->assertSame('too_short', $result['status']);
    }

    public function testSearchReturnsNotConfiguredWhenBcNotConfigured(): void
    {
        $service = $this->createService(null, false);
        $result = $service->search('Test Company');
        $this->assertSame('not_configured', $result['status']);
        $this->assertNotEmpty($result['error']);
    }

    public function testSearchReturnsSuccessWithResults(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('searchCustomers')
            ->with('Musterfirma')
            ->willReturn([
                ['No' => '10254', 'Name' => 'Musterfirma GmbH', 'City' => 'Berlin'],
            ]);

        $service = $this->createService($gateway);
        $result = $service->search('Musterfirma');
        $this->assertSame('success', $result['status']);
        $this->assertCount(1, $result['results']);
        $this->assertSame('10254', $result['results'][0]['No']);
    }

    public function testSearchReturnsNoResultsWhenEmpty(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('searchCustomers')
            ->willReturn([]);

        $service = $this->createService($gateway);
        $result = $service->search('xyz-nonexistent');
        $this->assertSame('no_results', $result['status']);
        $this->assertSame([], $result['results']);
    }

    public function testSearchReturnsErrorOnBcConnectionFailure(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('searchCustomers')
            ->willThrowException(new \RuntimeException('Connection refused'));

        $service = $this->createService($gateway);
        $result = $service->search('Musterfirma');
        $this->assertSame('error', $result['status']);
        $this->assertNotEmpty($result['error']);
    }

    public function testListForGridReturnsNotConfiguredWhenBcNotConfigured(): void
    {
        $service = $this->createService(null, false);
        $result = $service->listForGrid([]);

        $this->assertSame('not_configured', $result['status']);
        $this->assertSame([], $result['rows']);
        $this->assertSame(0, $result['total']);
    }

    public function testListForGridReturnsSuccessWithRowsAndTotal(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('listCustomers')
            ->with('Muster', 'Berlin', 10, 0, 'Name', 'asc')
            ->willReturn([
                'rows' => [
                    ['No' => '10000', 'Name' => 'Muster GmbH', 'City' => 'Berlin'],
                ],
                'total' => 42,
            ]);

        $service = $this->createService($gateway);
        $result = $service->listForGrid([
            'search' => 'Muster',
            'city' => 'Berlin',
            'limit' => 10,
            'offset' => 0,
            'order' => 'Name',
            'dir' => 'asc',
        ]);

        $this->assertSame('success', $result['status']);
        $this->assertCount(1, $result['rows']);
        $this->assertSame(42, $result['total']);
    }

    public function testListForGridReturnsErrorWhenGatewayFails(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('listCustomers')
            ->willThrowException(new \RuntimeException('Connection refused'));

        $service = $this->createService($gateway);
        $result = $service->listForGrid(['search' => 'Muster']);

        $this->assertSame('error', $result['status']);
        $this->assertSame([], $result['rows']);
        $this->assertSame(0, $result['total']);
    }

    public function testListForGridNormalizesLimitAndOffsetBounds(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->expects($this->once())
            ->method('listCustomers')
            ->with('', '', 100, 0, 'Name', 'asc')
            ->willReturn([
                'rows' => [],
                'total' => 0,
            ]);

        $service = $this->createService($gateway);
        $result = $service->listForGrid([
            'limit' => 999,
            'offset' => -5,
            'order' => 'Name',
            'dir' => 'asc',
        ]);

        $this->assertSame('success', $result['status']);
    }
}
