import Foundation
import Capacitor
import QuickLook

// Previews an already-downloaded file with iOS Quick Look — the native "look at this file" surface: swipe,
// pinch-zoom, print, and its own share button. Registered by cap sync as window.Capacitor.Plugins.FileOpener.
//
// WHY A PLUGIN: the app loads its UI from a REMOTE origin (remote.bizgaze.com), so it cannot open a local
// file:// URL in the WebView (cross-origin / capacitor local-serving isn't on this origin). @capacitor/share
// only offers the share SHEET ("open in another app"), not a preview. Only QLPreviewController, presented
// from native code, gives a real in-app preview. Quick Look picks the renderer from the file extension, which
// is why the web layer now saves downloads with a correct extension (see bzEnsureExt in home.html).
@objc(FileOpenerPlugin)
public class FileOpenerPlugin: CAPPlugin, CAPBridgedPlugin {
    public let identifier = "FileOpenerPlugin"
    public let jsName = "FileOpener"
    public let pluginMethods: [CAPPluginMethod] = [
        CAPPluginMethod(name: "preview", returnType: CAPPluginReturnPromise)
    ]

    // QLPreviewController holds its dataSource weakly, so we must keep a strong reference alive for the
    // lifetime of the presented preview — otherwise it deallocates and the preview shows blank.
    private var dataSource: QLDataSource?

    @objc func preview(_ call: CAPPluginCall) {
        guard let raw = call.getString("path"), !raw.isEmpty else {
            call.reject("path is required"); return
        }
        let url = FileOpenerPlugin.fileURL(from: raw)
        guard FileManager.default.fileExists(atPath: url.path) else {
            call.reject("file not found: \(url.path)"); return
        }
        DispatchQueue.main.async {
            let ds = QLDataSource(url: url)
            self.dataSource = ds
            let controller = QLPreviewController()
            controller.dataSource = ds
            controller.modalPresentationStyle = .fullScreen
            guard let base = self.bridge?.viewController else {
                call.reject("no view controller to present from"); return
            }
            // Present on top of whatever is already showing (a modal, another sheet) so it never fails silently.
            var presenter = base
            while let top = presenter.presentedViewController { presenter = top }
            presenter.present(controller, animated: true) {
                call.resolve(["ok": true])
            }
        }
    }

    // Accepts either a file:// URI (what Filesystem.writeFile returns) or a bare absolute path.
    private static func fileURL(from raw: String) -> URL {
        if raw.hasPrefix("file://") {
            if let u = URL(string: raw) { return u }
            // Un-encoded spaces make URL(string:) fail — percent-encode and retry before giving up.
            let encoded = raw.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? raw
            if let u = URL(string: encoded) { return u }
        }
        return URL(fileURLWithPath: raw)
    }
}

// Single-item data source. NSURL already conforms to QLPreviewItem.
final class QLDataSource: NSObject, QLPreviewControllerDataSource {
    private let url: URL
    init(url: URL) { self.url = url }
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int { 1 }
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        return url as NSURL
    }
}
