import { describe, it, expect } from "vitest";
import { ErrorCode } from "@pocketcoder/shared/constants";
import { MAX_FILE_SIZE, MAX_WRITE_SIZE, MAX_FS_ENTRIES, MAX_TREE_DEPTH, MAX_SEARCH_RESULTS, } from "@pocketcoder/shared/constants";
import { AppError } from "../../../errors/index.js";
import { validateReadSize, validateWriteSize, truncateListEntries, capTreeDepth, truncateSearchResults, } from "../limits.js";
describe("filesystem limits validation", () => {
    describe("validateReadSize", () => {
        it("should accept files within the 10MB limit", () => {
            expect(() => validateReadSize(0)).not.toThrow();
            expect(() => validateReadSize(1024)).not.toThrow();
            expect(() => validateReadSize(MAX_FILE_SIZE)).not.toThrow();
        });
        it("should reject reads exceeding 10MB", () => {
            expect(() => validateReadSize(MAX_FILE_SIZE + 1)).toThrow(AppError);
            try {
                validateReadSize(MAX_FILE_SIZE + 1);
            }
            catch (err) {
                const appErr = err;
                expect(appErr.code).toBe(ErrorCode.FILE_TOO_LARGE);
                expect(appErr.message).toContain("10MB");
                expect(appErr.details).toBeDefined();
                expect(appErr.details.size).toBe(MAX_FILE_SIZE + 1);
                expect(appErr.details.maxSize).toBe(MAX_FILE_SIZE);
            }
        });
        it("should include details in error response", () => {
            const size = 15 * 1024 * 1024; // 15 MB
            try {
                validateReadSize(size);
            }
            catch (err) {
                const appErr = err;
                const msgErr = appErr.toMessageError();
                expect(msgErr.code).toBe(ErrorCode.FILE_TOO_LARGE);
                expect(msgErr.details).toEqual({ size, maxSize: MAX_FILE_SIZE });
            }
        });
    });
    describe("validateWriteSize", () => {
        it("should accept content within the 1MB limit", () => {
            expect(() => validateWriteSize(0)).not.toThrow();
            expect(() => validateWriteSize(512)).not.toThrow();
            expect(() => validateWriteSize(MAX_WRITE_SIZE)).not.toThrow();
        });
        it("should reject writes exceeding 1MB", () => {
            expect(() => validateWriteSize(MAX_WRITE_SIZE + 1)).toThrow(AppError);
            try {
                validateWriteSize(MAX_WRITE_SIZE + 1);
            }
            catch (err) {
                const appErr = err;
                expect(appErr.code).toBe(ErrorCode.FILE_TOO_LARGE);
                expect(appErr.message).toContain("1MB");
                expect(appErr.details).toBeDefined();
                expect(appErr.details.size).toBe(MAX_WRITE_SIZE + 1);
                expect(appErr.details.maxSize).toBe(MAX_WRITE_SIZE);
            }
        });
        it("should include details in error response", () => {
            const size = 2 * 1024 * 1024; // 2 MB
            try {
                validateWriteSize(size);
            }
            catch (err) {
                const appErr = err;
                const msgErr = appErr.toMessageError();
                expect(msgErr.code).toBe(ErrorCode.FILE_TOO_LARGE);
                expect(msgErr.details).toEqual({ size, maxSize: MAX_WRITE_SIZE });
            }
        });
    });
    describe("truncateListEntries", () => {
        it("should return entries unchanged when under limit", () => {
            const entries = Array.from({ length: 100 }, (_, i) => `file-${i}`);
            const result = truncateListEntries(entries);
            expect(result.entries).toHaveLength(100);
            expect(result.truncated).toBe(false);
        });
        it("should return entries unchanged at exactly the limit", () => {
            const entries = Array.from({ length: MAX_FS_ENTRIES }, (_, i) => `file-${i}`);
            const result = truncateListEntries(entries);
            expect(result.entries).toHaveLength(MAX_FS_ENTRIES);
            expect(result.truncated).toBe(false);
        });
        it("should truncate list results at 10000", () => {
            const entries = Array.from({ length: MAX_FS_ENTRIES + 500 }, (_, i) => `file-${i}`);
            const result = truncateListEntries(entries);
            expect(result.entries).toHaveLength(MAX_FS_ENTRIES);
            expect(result.truncated).toBe(true);
            // First and last entries should be preserved in order
            expect(result.entries[0]).toBe("file-0");
            expect(result.entries[MAX_FS_ENTRIES - 1]).toBe(`file-${MAX_FS_ENTRIES - 1}`);
        });
    });
    describe("capTreeDepth", () => {
        it("should allow depths within the limit", () => {
            expect(capTreeDepth(1)).toBe(1);
            expect(capTreeDepth(10)).toBe(10);
            expect(capTreeDepth(MAX_TREE_DEPTH)).toBe(MAX_TREE_DEPTH);
        });
        it("should limit tree depth to 20 levels", () => {
            expect(capTreeDepth(21)).toBe(MAX_TREE_DEPTH);
            expect(capTreeDepth(100)).toBe(MAX_TREE_DEPTH);
            expect(capTreeDepth(999)).toBe(MAX_TREE_DEPTH);
        });
        it("should clamp negative values to 0", () => {
            expect(capTreeDepth(-1)).toBe(0);
            expect(capTreeDepth(-100)).toBe(0);
        });
        it("should pass through zero", () => {
            expect(capTreeDepth(0)).toBe(0);
        });
    });
    describe("truncateSearchResults", () => {
        it("should return results unchanged when under limit", () => {
            const results = Array.from({ length: 50 }, (_, i) => ({ line: i, text: `match-${i}` }));
            const result = truncateSearchResults(results);
            expect(result.results).toHaveLength(50);
            expect(result.truncated).toBe(false);
        });
        it("should return results unchanged at exactly the limit", () => {
            const results = Array.from({ length: MAX_SEARCH_RESULTS }, (_, i) => `match-${i}`);
            const result = truncateSearchResults(results);
            expect(result.results).toHaveLength(MAX_SEARCH_RESULTS);
            expect(result.truncated).toBe(false);
        });
        it("should limit search to 1000 results", () => {
            const results = Array.from({ length: MAX_SEARCH_RESULTS + 200 }, (_, i) => `match-${i}`);
            const result = truncateSearchResults(results);
            expect(result.results).toHaveLength(MAX_SEARCH_RESULTS);
            expect(result.truncated).toBe(true);
            // First and last entries should be preserved in order
            expect(result.results[0]).toBe("match-0");
            expect(result.results[MAX_SEARCH_RESULTS - 1]).toBe(`match-${MAX_SEARCH_RESULTS - 1}`);
        });
        it("should include details in error response for rejected reads", () => {
            // Verifying the full error chain: validate -> AppError -> MessageError with details
            try {
                validateReadSize(MAX_FILE_SIZE + 1024);
            }
            catch (err) {
                const appErr = err;
                const msgErr = appErr.toMessageError();
                expect(msgErr.code).toBe(ErrorCode.FILE_TOO_LARGE);
                expect(msgErr.message).toBeDefined();
                expect(msgErr.details).toBeDefined();
                expect(typeof msgErr.details.size).toBe("number");
                expect(typeof msgErr.details.maxSize).toBe("number");
            }
        });
    });
});
//# sourceMappingURL=limits.test.js.map