import XCTest
@testable import Neon_Vision_Editor

@MainActor
final class EditorViewModelFileOpenTests: XCTestCase {
    private var temporaryDirectoryURL: URL!

    override func setUpWithError() throws {
        temporaryDirectoryURL = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: temporaryDirectoryURL, withIntermediateDirectories: true)
    }

    override func tearDownWithError() throws {
        if let temporaryDirectoryURL {
            try? FileManager.default.removeItem(at: temporaryDirectoryURL)
        }
        temporaryDirectoryURL = nil
    }

    func testSupportedEditorFileURLsCoverIOSMatrixExtensions() {
        let supportedNames = [
            "sample.txt",
            "sample.md",
            "sample.json",
            "sample.xml",
            "sample.plist",
            "sample.sh"
        ]

        for name in supportedNames {
            let url = temporaryDirectoryURL.appendingPathComponent(name)
            XCTAssertTrue(
                EditorViewModel.isSupportedEditorFileURL(url),
                "Expected \(name) to be supported by external document flows."
            )
        }
    }

    func testOpenFileLoadsContentAndReusesExistingTab() async throws {
        let url = temporaryDirectoryURL.appendingPathComponent("notes.md")
        let expectedContent = "# Hello\n\nThis file came from an external open flow.\n"
        try expectedContent.write(to: url, atomically: true, encoding: .utf8)

        let viewModel = EditorViewModel()
        viewModel.resetTabsForSessionRestore()
        XCTAssertTrue(viewModel.openFile(url: url))

        let loadedTab = try await waitForLoadedTab(in: viewModel, matching: url)
        XCTAssertEqual(loadedTab.content, expectedContent)
        XCTAssertEqual(loadedTab.language, "markdown")
        XCTAssertEqual(viewModel.tabs.count, 1)
        XCTAssertEqual(viewModel.selectedTab?.id, loadedTab.id)

        XCTAssertTrue(viewModel.openFile(url: url))

        let reusedTab = try await waitForLoadedTab(in: viewModel, matching: url)
        XCTAssertEqual(viewModel.tabs.count, 1)
        XCTAssertEqual(reusedTab.id, loadedTab.id)
        XCTAssertEqual(viewModel.selectedTab?.id, loadedTab.id)
    }

    private func waitForLoadedTab(in viewModel: EditorViewModel, matching url: URL) async throws -> TabData {
        let timeout = Date().addingTimeInterval(5)
        while Date() < timeout {
            if let tab = viewModel.selectedTab,
               tab.fileURL?.standardizedFileURL == url.standardizedFileURL,
               !tab.isLoadingContent {
                return tab
            }
            try await Task.sleep(nanoseconds: 50_000_000)
        }
        XCTFail("Timed out waiting for \(url.lastPathComponent) to load")
        throw CancellationError()
    }
}
