// SPDX-FileCopyrightText: 2026 John Burwell and contributors
// SPDX-License-Identifier: AGPL-3.0-or-later

import Cocoa
import OSLog
import Quartz

final class PreviewViewController: NSViewController, QLPreviewingController {
    private let logger = Logger(
        subsystem: "us.b-wells.World-Manager-for-Minecraft",
        category: "PreviewExtension"
    )

    private var currentInspection: MinecraftPackageInspector.InspectionResult?
    private let imageView = NSImageView()
    private let scrollView = NSScrollView()

    override func loadView() {
        let rootView = NSView(frame: NSRect(x: 0, y: 0, width: 900, height: 700))
        rootView.wantsLayer = true
        rootView.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor

        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.imageScaling = .scaleProportionallyUpOrDown
        imageView.imageAlignment = .alignCenter

        let containerView = NSView()
        containerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.addSubview(imageView)

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.drawsBackground = false
        scrollView.hasVerticalScroller = true
        scrollView.hasHorizontalScroller = true
        scrollView.documentView = containerView

        rootView.addSubview(scrollView)
        view = rootView

        NSLayoutConstraint.activate([
            scrollView.leadingAnchor.constraint(equalTo: rootView.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: rootView.trailingAnchor),
            scrollView.topAnchor.constraint(equalTo: rootView.topAnchor),
            scrollView.bottomAnchor.constraint(equalTo: rootView.bottomAnchor),

            containerView.leadingAnchor.constraint(equalTo: imageView.leadingAnchor, constant: -32),
            containerView.trailingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 32),
            containerView.topAnchor.constraint(equalTo: imageView.topAnchor, constant: -32),
            containerView.bottomAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 32),

            imageView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
            imageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor)
        ])
    }

    func preparePreviewOfFile(at url: URL) async throws {
        logger.notice("Preview extension hit: \(url.path, privacy: .public)")

        if let currentInspection {
            MinecraftPackageInspector.cleanup(currentInspection)
            self.currentInspection = nil
        }

        let inspection = try MinecraftPackageInspector.inspectArchive(at: url)
        let image = makePreviewImage(for: inspection)

        await MainActor.run {
            imageView.image = image
            updateImageConstraints(for: image)
        }

        currentInspection = inspection
    }

    private func makePreviewImage(for inspection: MinecraftPackageInspector.InspectionResult) -> NSImage? {
        if let iconURL = inspection.iconURL,
           let image = NSImage(contentsOf: iconURL) {
            return image
        }

        guard let cgImage = MinecraftPackageThumbnailRenderer.makeThumbnail(
            for: inspection,
            size: CGSize(width: 480, height: 480),
            scale: NSScreen.main?.backingScaleFactor ?? 2
        ) else {
            return nil
        }

        return NSImage(cgImage: cgImage, size: NSSize(width: 480, height: 480))
    }

    private func updateImageConstraints(for image: NSImage?) {
        imageView.constraints.forEach { imageView.removeConstraint($0) }

        guard let image, image.size.width > 0, image.size.height > 0 else {
            return
        }

        NSLayoutConstraint.activate([
            imageView.widthAnchor.constraint(equalToConstant: image.size.width),
            imageView.heightAnchor.constraint(equalToConstant: image.size.height)
        ])
    }

    deinit {
        if let currentInspection {
            MinecraftPackageInspector.cleanup(currentInspection)
        }
    }
}
