package tech.easyflow.common.filestorage;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

/**
 * {@link FileStorageWriteHandle} 编解码与安全边界测试。
 */
public class FileStorageWriteHandleTest {

    /**
     * 验证 locator 可无损往返且相对目录会规范化为尾斜杠形式。
     */
    @Test
    public void locatorRoundTripPreservesPhysicalLocation() {
        FileStorageWriteHandle handle = new FileStorageWriteHandle(
                "xFileStorage", "minio-1", "easyflow/", "skill-content/ab", "content.bin");

        String locator = handle.encodeLocator();
        FileStorageWriteHandle decoded = FileStorageWriteHandle.decodeLocator(locator);

        assertEquals(handle, decoded);
        assertEquals("skill-content/ab/", decoded.getPath());
        assertTrue(locator.startsWith("efsw1."));
        assertFalse(locator.contains("="));
        assertTrue(locator.length() <= 2048);
    }

    /**
     * 验证篡改后的 locator 无法绕过完整性校验。
     */
    @Test
    public void tamperedLocatorIsRejected() {
        FileStorageWriteHandle handle = new FileStorageWriteHandle(
                "local", "", "/var/lib/easyflow", "skill-content", "content.bin");
        String locator = handle.encodeLocator();
        char replacement = locator.endsWith("A") ? 'B' : 'A';
        String tampered = locator.substring(0, locator.length() - 1) + replacement;

        assertThrows(IllegalArgumentException.class,
                () -> FileStorageWriteHandle.decodeLocator(tampered));
    }

    /**
     * 验证相对路径穿越、绝对路径与不可移植文件名都会被拒绝。
     */
    @Test
    public void unsafePathsAreRejected() {
        assertThrows(IllegalArgumentException.class,
                () -> new FileStorageWriteHandle("local", "", "/tmp/easyflow", "../outside", "file.bin"));
        assertThrows(IllegalArgumentException.class,
                () -> new FileStorageWriteHandle("local", "", "/tmp/easyflow", "/absolute", "file.bin"));
        assertThrows(IllegalArgumentException.class,
                () -> new FileStorageWriteHandle("local", "", "/tmp/easyflow", "safe", "../file.bin"));
        assertThrows(IllegalArgumentException.class,
                () -> new FileStorageWriteHandle("local", "", "/tmp/easyflow", "safe", "CON"));
    }

    /**
     * 验证句柄在构造阶段就受数据库 VARCHAR(2048) locator 预算约束。
     */
    @Test
    public void handleExceedingPersistentLocatorBudgetIsRejected() {
        String oversizedBasePath = "/" + "a".repeat(1_700);

        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
                () -> new FileStorageWriteHandle(
                        "xFileStorage", "minio", oversizedBasePath, "skill-content", "content.bin"));

        assertTrue(exception.getMessage().contains("2048"));
    }

    /**
     * 验证解码器在 Base64 解码前拒绝超过数据库字段预算的输入。
     */
    @Test
    public void oversizedLocatorTextIsRejectedBeforeDecode() {
        String locator = "efsw1." + "A".repeat(2048);

        assertThrows(IllegalArgumentException.class,
                () -> FileStorageWriteHandle.decodeLocator(locator));
    }
}
