<?php

namespace Tests\Unit\Storage;

use CodeIgniter\HTTP\DownloadResponse;
use Tests\Support\Storage\StorageTestCase;

/**
 * @internal
 */
final class FileStorageServiceTest extends StorageTestCase
{
    public function testResolveKeyWithSubFolder(): void
    {
        $key = storage()->resolveKey('policy', 'policy_pdf', 'abc.pdf');

        $this->assertSame('uploads/policy/policy_pdf/abc.pdf', $key);
    }

    public function testResolveKeyWithoutSubFolder(): void
    {
        $key = storage()->resolveKey('endorsement', '', 'original.pdf');

        $this->assertSame('uploads/endorsement/original.pdf', $key);
    }

    public function testUploadModuleFileStoresPolicyPdf(): void
    {
        $file = $this->createUploadedFile('%PDF', 'policy.pdf', 'application/pdf');

        $storedName = storage()->uploadModuleFile($file, 'policy', 'policy_pdf');

        $this->assertNotSame('', $storedName);
        $this->assertTrue(storage()->exists('policy', 'policy_pdf', $storedName));
    }

    public function testReadWriteAndDeleteByModule(): void
    {
        storage()->put(storage()->resolveKey('policy', 'policy_md', 'doc.md'), '# md');

        $this->assertTrue(storage()->exists('policy', 'policy_md', 'doc.md'));
        $this->assertSame('# md', storage()->read('policy', 'policy_md', 'doc.md'));

        $this->assertTrue(storage()->delete('policy', 'policy_md', 'doc.md'));
        $this->assertFalse(storage()->exists('policy', 'policy_md', 'doc.md'));
    }

    public function testGetLocalPathForProcessingPointsToWritableFile(): void
    {
        $fileName = 'local-path.pdf';
        storage()->put(storage()->resolveKey('policy', 'policy_pdf', $fileName), 'local');

        $path = storage()->getLocalPathForProcessing('policy', 'policy_pdf', $fileName);

        $this->assertFileExists($path);
        $this->assertSame('local', file_get_contents($path));
    }

    public function testCleanupTempPathRemovesS3StyleTempFileOnly(): void
    {
        $tempPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('s3_', true) . '_policy.pdf';
        file_put_contents($tempPath, 'temp-pdf');

        $this->assertTrue(storage()->isS3TempProcessingPath($tempPath));
        $this->assertTrue(storage_cleanup_temp($tempPath));
        $this->assertFileDoesNotExist($tempPath);

        $fileName = 'keep-local.pdf';
        storage()->put(storage()->resolveKey('policy', 'policy_pdf', $fileName), 'keep');
        $localPath = storage()->getLocalPathForProcessing('policy', 'policy_pdf', $fileName);

        $this->assertFalse(storage()->isS3TempProcessingPath($localPath));
        $this->assertFalse(storage_cleanup_temp($localPath));
        $this->assertFileExists($localPath);
    }

    public function testCopyBetweenKeys(): void
    {
        storage()->put(storage()->resolveKey('policy', 'policy_pdf', 'from.pdf'), 'from');
        storage()->copy('policy', 'policy_pdf', 'from.pdf', 'policy', 'policy_pdf', 'to.pdf');

        $this->assertSame('from', storage()->read('policy', 'policy_pdf', 'to.pdf'));
    }

    public function testDownloadReturnsAttachmentResponse(): void
    {
        storage()->put(storage()->resolveKey('policy', 'policy_pdf', 'dl.pdf'), 'download');

        $response = storage()->download('policy', 'policy_pdf', 'dl.pdf');

        $this->assertInstanceOf(DownloadResponse::class, $response);
        $this->assertDownloadHeaders($response, 'attachment');
        $this->assertGreaterThan(0, $response->getContentLength());
    }

    public function testGetTemporaryUrlForLocalUsesBaseUrl(): void
    {
        storage()->put(storage()->resolveKey('policy', 'policy_pdf', 'url.pdf'), 'url');

        $url = storage()->getTemporaryUrl('policy', 'policy_pdf', 'url.pdf');

        $this->assertStringContainsString('uploads/policy/policy_pdf/url.pdf', $url);
    }
}

/**
 * @internal
 */
final class StorageHelperTest extends StorageTestCase
{
    public function testStorageUploadIfValidReturnsNullForInvalidFile(): void
    {
        $this->assertNull(storage_upload_if_valid(null, 'policy', 'policy_pdf'));
    }

    public function testStorageExistsReturnsFalseForEmptyFileName(): void
    {
        $this->assertFalse(storage_exists('policy', 'policy_pdf', ''));
    }

    public function testStoragePutAndReadRoundTrip(): void
    {
        storage_put('policy', 'policy_md', 'helper.md', '# helper');

        $this->assertTrue(storage_exists('policy', 'policy_md', 'helper.md'));
        $this->assertSame('# helper', storage_read('policy', 'policy_md', 'helper.md'));
    }

    public function testStorageDeleteRemovesFile(): void
    {
        storage_put('endorsement', 'endorsement_pdf', 'delete-me.pdf', 'pdf');
        $this->assertTrue(storage_delete('endorsement', 'endorsement_pdf', 'delete-me.pdf'));
        $this->assertFalse(storage_exists('endorsement', 'endorsement_pdf', 'delete-me.pdf'));
    }

    public function testStorageInlineSetsInlineDisposition(): void
    {
        storage_put('policy', 'policy_pdf', 'inline.pdf', 'inline');

        $response = storage_inline('policy', 'policy_pdf', 'inline.pdf');

        $this->assertStringContainsString('inline', $response->getHeaderLine('Content-Disposition'));
    }

    public function testStorageLocalPathMatchesStoredFile(): void
    {
        storage_put('policy', 'policy_pdf', 'process.pdf', 'process');

        $path = storage_local_path('policy', 'policy_pdf', 'process.pdf');

        $this->assertFileExists($path);
        $this->assertSame('process', file_get_contents($path));
    }
}
