package dev.photosync.core.config;

import dev.photosync.core.PhotoSync;
import dev.photosync.core.capture.CaptureOrigin;
import dev.photosync.core.capture.CapturedScreenshot;
import dev.photosync.core.provider.AlbumRef;
import dev.photosync.core.provider.immich.ImmichProviderFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

/** Switching the storage location really moves the settings file, and nothing else. */
class PhotoSyncRelocationTest {

    @TempDir
    Path temp;

    private ConfigLocations locations() {
        return new ConfigLocations(temp.resolve("instance"), temp.resolve("user"));
    }

    private PhotoSync started(ConfigLocations locations) {
        PhotoSync core = new PhotoSync(locations, List.of(new ImmichProviderFactory()));
        core.start();
        return core;
    }

    @Test
    void movesSettingsFileAndRemembersTheChoice() throws Exception {
        Path instance = temp.resolve("instance");
        Path user = temp.resolve("user");
        ConfigLocations locations = locations();

        PhotoSync core = started(locations);
        core.config().update(current -> current.toBuilder().albumId("first").build());
        assertTrue(Files.exists(instance.resolve("photosync.json")));

        core.config().update(current -> current.toBuilder().location(ConfigLocation.USER).build());

        // The file followed the setting, and the marker says where it went.
        assertFalse(Files.exists(instance.resolve("photosync.json")));
        assertTrue(Files.exists(user.resolve("photosync.json")));
        assertEquals(ConfigLocation.USER, locations.resolve());
        assertEquals(ConfigLocation.USER, core.config().current().location());
        assertEquals(user, core.dataDirectory());

        // Later saves land in the new place.
        core.config().update(current -> current.toBuilder().albumId("second").build());
        assertTrue(Files.readString(user.resolve("photosync.json")).contains("\"second\""));

        core.close();

        // A fresh PhotoSync resolves the marker and reads the moved file.
        PhotoSync reopened = started(locations);
        assertEquals(ConfigLocation.USER, reopened.config().current().location());
        assertEquals("second", reopened.config().current().albumId());
        reopened.close();
    }

    @Test
    void switchesBackToTheInstanceDirectory() throws Exception {
        Path instance = temp.resolve("instance");
        Path user = temp.resolve("user");
        ConfigLocations locations = locations();

        PhotoSync core = started(locations);
        core.config().update(current -> current.toBuilder().location(ConfigLocation.USER).build());
        assertTrue(Files.exists(user.resolve("photosync.json")));

        core.config().update(current -> current.toBuilder().location(ConfigLocation.INSTANCE).build());

        assertTrue(Files.exists(instance.resolve("photosync.json")));
        assertFalse(Files.exists(user.resolve("photosync.json")));
        assertEquals(ConfigLocation.INSTANCE, locations.resolve());
        assertEquals(instance, core.dataDirectory());
        core.close();
    }

    @Test
    void leavesTheUploadQueueInTheInstanceDirectory() throws Exception {
        Path instance = temp.resolve("instance");
        Path user = temp.resolve("user");
        Path shot = temp.resolve("screenshot.png");
        Files.writeString(shot, "fake png");
        ConfigLocations locations = locations();

        PhotoSync core = started(locations);
        core.queue().enqueue(CapturedScreenshot.of(shot, CaptureOrigin.MANUAL), AlbumRef.library(), "test");
        assertTrue(Files.exists(instance.resolve("uploads.json")));

        core.config().update(current -> current.toBuilder().location(ConfigLocation.USER).build());

        // The queue references instance-local screenshot paths, so it stays put.
        assertTrue(Files.exists(instance.resolve("uploads.json")));
        assertFalse(Files.exists(user.resolve("uploads.json")));
        core.close();
    }
}
