import Testing
import Foundation
@testable import 康康

struct ModelStoreDownloadSupportTests {

    private func isolatedStore() throws -> ModelStore {
        let temp = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        return try ModelStore(rootURL: temp)
    }

    @Test func fileURLPointsIntoModelFolder() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let url = store.fileURL(for: .llm, relativePath: "config.json")
        #expect(url == store.localURL(for: .llm).appendingPathComponent("config.json"))
    }

    @Test func localBytesZeroWhenMissing() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        #expect(store.localBytes(for: .llm, relativePath: "config.json") == 0)
    }

    @Test func localBytesReturnsFileSize() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let folder = store.localURL(for: .llm)
        try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
        try Data(repeating: 7, count: 512).write(to: folder.appendingPathComponent("config.json"))
        #expect(store.localBytes(for: .llm, relativePath: "config.json") == 512)
    }

    @Test func isCompleteFalseWhenFilesMissing() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let files = [ModelFile(path: "a.bin", bytes: 1024)]
        #expect(store.isComplete(for: .llm, files: files) == false)
    }

    @Test func isCompleteTrueWhenAllFilesPresentWithExpectedSize() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let folder = store.localURL(for: .llm)
        try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
        try Data(repeating: 1, count: 1024).write(to: folder.appendingPathComponent("a.bin"))
        let files = [ModelFile(path: "a.bin", bytes: 1024)]
        #expect(store.isComplete(for: .llm, files: files) == true)
    }

    @Test func isCompleteFalseWhenSizeMismatch() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let folder = store.localURL(for: .llm)
        try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
        try Data(repeating: 1, count: 999).write(to: folder.appendingPathComponent("a.bin"))
        let files = [ModelFile(path: "a.bin", bytes: 1024)]
        #expect(store.isComplete(for: .llm, files: files) == false)
    }

    @Test func importModelCopiesFolderAndMarksReady() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }

        let src = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: src, withIntermediateDirectories: true)
        defer { try? FileManager.default.removeItem(at: src) }
        try "{}".write(to: src.appendingPathComponent("config.json"), atomically: true, encoding: .utf8)
        try "x".write(to: src.appendingPathComponent("tokenizer.json"), atomically: true, encoding: .utf8)

        try store.importModel(.llm, from: src)

        #expect(store.isReady(.llm) == true)
        #expect(FileManager.default.fileExists(
            atPath: store.fileURL(for: .llm, relativePath: "tokenizer.json").path))
    }

    @Test func importModelThrowsWhenNoConfig() throws {
        let store = try isolatedStore()
        defer { try? FileManager.default.removeItem(at: store.rootURL) }
        let src = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: src, withIntermediateDirectories: true)
        defer { try? FileManager.default.removeItem(at: src) }

        #expect(throws: (any Error).self) {
            try store.importModel(.llm, from: src)
        }
    }
}
