import Foundation
import QuickLook
import SwiftUI

@MainActor
class QuickLookManager: NSObject, ObservableObject {
    static let shared = QuickLookManager()

    @Published var isPresenting = false
    @Published var downloadProgress: Double = 0
    @Published var isDownloading = false

    private var previewItems: [QLPreviewItem] = []
    private var currentFile: FileEntry?
    private let temporaryDirectory: URL

    override init() {
        // Create a temporary directory for downloaded files
        let tempDir = FileManager.default.temporaryDirectory.appendingPathComponent("QuickLookCache", isDirectory: true)
        try? FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
        self.temporaryDirectory = tempDir
        super.init()

        // Clean up old files on init
        cleanupTemporaryFiles()
    }

    func previewFile(_ file: FileEntry, apiClient: APIClient) async throws {
        guard !file.isDir else {
            throw QuickLookError.isDirectory
        }

        currentFile = file
        isDownloading = true
        downloadProgress = 0

        do {
            let localURL = try await downloadFileForPreview(file: file, apiClient: apiClient)

            // Create preview item
            let previewItem = PreviewItem(url: localURL, title: file.name)
            previewItems = [previewItem]

            isDownloading = false
            isPresenting = true
        } catch {
            isDownloading = false
            throw error
        }
    }

    private func downloadFileForPreview(file: FileEntry, apiClient: APIClient) async throws -> URL {
        // Check if file is already cached
        let cachedURL = temporaryDirectory.appendingPathComponent(file.name)

        // For now, always download fresh (could implement proper caching later)
        if FileManager.default.fileExists(atPath: cachedURL.path) {
            try FileManager.default.removeItem(at: cachedURL)
        }

        // Download the file
        let data = try await apiClient.downloadFile(path: file.path) { progress in
            Task { @MainActor in
                self.downloadProgress = progress
            }
        }

        // Save to temporary location
        try data.write(to: cachedURL)

        return cachedURL
    }

    func cleanupTemporaryFiles() {
        // Remove files older than 1 hour
        let oneHourAgo = Date().addingTimeInterval(-3_600)

        guard let files = try? FileManager.default.contentsOfDirectory(
            at: temporaryDirectory,
            includingPropertiesForKeys: [.creationDateKey]
        ) else {
            return
        }

        for file in files {
            if let creationDate = try? file.resourceValues(forKeys: [.creationDateKey]).creationDate,
               creationDate < oneHourAgo
            {
                try? FileManager.default.removeItem(at: file)
            }
        }
    }

    func makePreviewController() -> QLPreviewController {
        let controller = QLPreviewController()
        controller.dataSource = self
        controller.delegate = self
        return controller
    }
}

// MARK: - QLPreviewControllerDataSource

extension QuickLookManager: QLPreviewControllerDataSource {
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        previewItems.count
    }

    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        previewItems[index]
    }
}

// MARK: - QLPreviewControllerDelegate

extension QuickLookManager: QLPreviewControllerDelegate {
    nonisolated func previewControllerDidDismiss(_ controller: QLPreviewController) {
        Task { @MainActor in
            isPresenting = false
            previewItems = []
            currentFile = nil
        }
    }
}

// MARK: - Preview Item

private class PreviewItem: NSObject, QLPreviewItem {
    let previewItemURL: URL?
    let previewItemTitle: String?

    init(url: URL, title: String) {
        self.previewItemURL = url
        self.previewItemTitle = title
    }
}

// MARK: - Errors

enum QuickLookError: LocalizedError {
    case isDirectory
    case downloadFailed
    case unsupportedFileType

    var errorDescription: String? {
        switch self {
        case .isDirectory:
            "Cannot preview directories"
        case .downloadFailed:
            "Failed to download file"
        case .unsupportedFileType:
            "This file type cannot be previewed"
        }
    }
}
