package io.cameleer.server.app.storage;

import io.cameleer.server.core.storage.ArtifactCoordinates;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

class FilesystemArtifactStoreTest {

    @Test
    void roundTripsBytes(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        ArtifactCoordinates c = new ArtifactCoordinates("default", UUID.randomUUID(), 1);

        byte[] payload = "hello-jar".getBytes();
        store.put(c, new ByteArrayInputStream(payload), payload.length);

        assertThat(store.exists(c)).isTrue();
        try (InputStream in = store.get(c)) {
            assertThat(in.readAllBytes()).isEqualTo(payload);
        }
    }

    @Test
    void deleteRemovesFileAndEmptyParents(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        UUID appId = UUID.randomUUID();
        ArtifactCoordinates c = new ArtifactCoordinates("default", appId, 1);
        store.put(c, new ByteArrayInputStream("x".getBytes()), 1);

        store.delete(c);

        assertThat(store.exists(c)).isFalse();
        // {tmp}/{appId}/v1/ should be gone too
        assertThat(Files.exists(tmp.resolve(appId.toString()).resolve("v1"))).isFalse();
    }

    @Test
    void deleteIsIdempotent(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        ArtifactCoordinates c = new ArtifactCoordinates("default", UUID.randomUUID(), 1);
        store.delete(c); // no exception
        assertThat(store.exists(c)).isFalse();
    }

    @Test
    void locatorMatchesLegacyAbsolutePath(@TempDir Path tmp) {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        UUID appId = UUID.fromString("11111111-1111-1111-1111-111111111111");
        ArtifactCoordinates c = new ArtifactCoordinates("default", appId, 7);
        assertThat(store.locator(c))
                .isEqualTo(tmp.resolve("11111111-1111-1111-1111-111111111111/v7/app.jar").toString());
    }

    @Test
    void putOverwritesExistingArtifactWithDifferentContent(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        ArtifactCoordinates c = new ArtifactCoordinates("default", UUID.randomUUID(), 1);

        store.put(c, new ByteArrayInputStream("v1-bytes".getBytes()), 8);
        store.put(c, new ByteArrayInputStream("v2-different-bytes".getBytes()), 18);

        try (InputStream in = store.get(c)) {
            assertThat(new String(in.readAllBytes())).isEqualTo("v2-different-bytes");
        }
    }

    @Test
    void sizeReturnsActualOnDiskBytes(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        ArtifactCoordinates c = new ArtifactCoordinates("default", UUID.randomUUID(), 1);
        byte[] payload = new byte[1234];
        store.put(c, new java.io.ByteArrayInputStream(payload), payload.length);
        assertThat(store.size(c)).isEqualTo(1234L);
    }

    @Test
    void deleteLeavesAppDirAloneWhenSiblingVersionExists(@TempDir Path tmp) throws Exception {
        FilesystemArtifactStore store = new FilesystemArtifactStore(tmp.toString());
        UUID appId = UUID.randomUUID();
        ArtifactCoordinates v1 = new ArtifactCoordinates("default", appId, 1);
        ArtifactCoordinates v2 = new ArtifactCoordinates("default", appId, 2);

        store.put(v1, new ByteArrayInputStream("a".getBytes()), 1);
        store.put(v2, new ByteArrayInputStream("b".getBytes()), 1);

        store.delete(v1);

        // v1/ should be gone, but v2/ and the appId/ dir should remain (sibling lives there)
        assertThat(Files.exists(tmp.resolve(appId.toString()).resolve("v1"))).isFalse();
        assertThat(Files.exists(tmp.resolve(appId.toString()).resolve("v2/app.jar"))).isTrue();
        assertThat(Files.exists(tmp.resolve(appId.toString()))).isTrue();
    }
}
