<?php

namespace Tests\App\Libraries;

use App\Libraries\FinancialAttachmentService;
use CodeIgniter\HTTP\Files\UploadedFile;
use CodeIgniter\Test\CIUnitTestCase;

class FinancialAttachmentServiceTest extends CIUnitTestCase
{
    private FinancialAttachmentService $service;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = new FinancialAttachmentService();
    }

    public function testSaveUploadedFileReturnsNullForInvalidInput(): void
    {
        $this->assertNull($this->service->saveUploadedFile(null, 'payments'));

        $file = $this->createMock(UploadedFile::class);
        $file->method('isValid')->willReturn(false);

        $this->assertNull($this->service->saveUploadedFile($file, 'payments'));
    }

    public function testSaveUploadedFileRejectsUnsupportedMimeType(): void
    {
        $file = $this->createMock(UploadedFile::class);
        $file->method('isValid')->willReturn(true);
        $file->method('hasMoved')->willReturn(false);
        $file->method('getSize')->willReturn(1000);
        $file->method('getMimeType')->willReturn('text/plain');
        $file->method('getClientExtension')->willReturn('txt');

        $this->expectException(\RuntimeException::class);
        $this->expectExceptionMessage('Unsupported file type.');

        $this->service->saveUploadedFile($file, 'payments');
    }

    public function testSaveUploadedFileRejectsOversizedFiles(): void
    {
        $file = $this->createMock(UploadedFile::class);
        $file->method('isValid')->willReturn(true);
        $file->method('hasMoved')->willReturn(false);
        $file->method('getSize')->willReturn(5242881);
        $file->method('getMimeType')->willReturn('application/pdf');
        $file->method('getClientExtension')->willReturn('pdf');

        $this->expectException(\RuntimeException::class);
        $this->expectExceptionMessage('File too large.');

        $this->service->saveUploadedFile($file, 'payments');
    }

    public function testSaveUploadedFileMovesValidFilesAndReturnsRandomName(): void
    {
        $file = $this->createMock(UploadedFile::class);
        $file->method('isValid')->willReturn(true);
        $file->method('hasMoved')->willReturn(false);
        $file->method('getSize')->willReturn(1024);
        $file->method('getMimeType')->willReturn('application/pdf');
        $file->method('getClientExtension')->willReturn('pdf');
        $file->method('getRandomName')->willReturn('proof.pdf');

        $file->expects($this->once())
            ->method('move')
            ->with($this->stringContains('writable/uploads/payments'), 'proof.pdf');

        $this->assertSame('proof.pdf', $this->service->saveUploadedFile($file, 'payments'));
    }

    public function testResolvePathUsesBasenameAndReturnsNullForMissingFiles(): void
    {
        $dir = $this->service->ensureSubdir('receipts');
        $path = $dir . DIRECTORY_SEPARATOR . 'receipt.pdf';
        file_put_contents($path, 'pdf');

        $this->assertSame($path, $this->service->resolvePath('receipts', '../receipt.pdf'));
        $this->assertNull($this->service->resolvePath('receipts', 'missing.pdf'));
    }

    public function testDetectMimeReturnsKnownMimeForExistingFile(): void
    {
        $dir = $this->service->ensureSubdir('mime-tests');
        $path = $dir . DIRECTORY_SEPARATOR . 'image.png';
        file_put_contents(
            $path,
            base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aap8AAAAASUVORK5CYII=')
        );

        $mime = $this->service->detectMime($path);

        $this->assertStringContainsString('image/', $mime);
    }
}
