<?php

declare(strict_types=1);

namespace OCA\Mitgliederverwaltung\Tests\Integration;

use OCA\Mitgliederverwaltung\Controller\AuditController;
use OCA\Mitgliederverwaltung\Service\AuditService;
use OCP\AppFramework\Http;
use OCP\IRequest;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

/**
 * Integration-level tests for AuditController API endpoints.
 */
class AuditControllerTest extends TestCase {

    private AuditController $controller;
    private AuditService&MockObject $auditService;
    private IRequest&MockObject $request;
    private LoggerInterface&MockObject $logger;

    protected function setUp(): void {
        parent::setUp();

        $this->auditService = $this->createMock(AuditService::class);
        $this->request = $this->createMock(IRequest::class);
        $this->logger = $this->createMock(LoggerInterface::class);

        $this->controller = new AuditController(
            'mitgliederverwaltung',
            $this->request,
            $this->auditService,
            $this->logger
        );
    }

    // ── GET /api/v1/audit-log (index) ──────────────────────────────

    public function testIndexReturns200WithDefaults(): void {
        $entries = [
            ['id' => 1, 'entitaet' => 'member', 'aktion' => 'create'],
        ];

        $this->request->method('getParam')->willReturn(null);
        $this->auditService->method('getLog')
            ->with(null, null, null, null, null, 50, 0)
            ->willReturn($entries);

        $response = $this->controller->index();

        $this->assertSame(Http::STATUS_OK, $response->getStatus());
        $this->assertCount(1, $response->getData());
    }

    public function testIndexReturns200WithFilters(): void {
        $this->request->method('getParam')
            ->willReturnCallback(function ($name) {
                return match ($name) {
                    'entitaet' => 'member',
                    'entitaetId' => '42',
                    'ncUserId' => 'admin',
                    'from' => '2026-01-01',
                    'to' => '2026-12-31',
                    'limit' => '10',
                    'offset' => '5',
                    default => null,
                };
            });

        $this->auditService->method('getLog')
            ->with('member', 42, 'admin', '2026-01-01', '2026-12-31', 10, 5)
            ->willReturn([]);

        $response = $this->controller->index();

        $this->assertSame(Http::STATUS_OK, $response->getStatus());
    }

    public function testIndexReturns500OnException(): void {
        $this->request->method('getParam')->willReturn(null);
        $this->auditService->method('getLog')
            ->willThrowException(new \RuntimeException('DB error'));

        $response = $this->controller->index();

        $this->assertSame(Http::STATUS_INTERNAL_SERVER_ERROR, $response->getStatus());
        $this->assertArrayHasKey('error', $response->getData());
    }

    public function testIndexReturns200WithEmptyResult(): void {
        $this->request->method('getParam')->willReturn(null);
        $this->auditService->method('getLog')->willReturn([]);

        $response = $this->controller->index();

        $this->assertSame(Http::STATUS_OK, $response->getStatus());
        $this->assertSame([], $response->getData());
    }
}
