import AppKit
import SwiftUI

/// 悬浮窗口控制器：管理毛玻璃 + SwiftUI 视图嵌入 + 窗口显隐
final class FloatingWindowController: NSWindowController {
    private var hostingView: NSHostingView<ContentView>?
    private var visualEffect: NSVisualEffectView!
    private let tinyAlphaBackground = NSColor.white.withAlphaComponent(0.00001)

    private let debugLogPath = NSHomeDirectory() + "/Desktop/fm_debug.log"

    convenience init() {
        let window = FloatingWindow(
            contentRect: NSRect(x: 0, y: 0, width: 250, height: 300),
            styleMask: [.borderless, .resizable],
            backing: .buffered,
            defer: false
        )
        window.isReleasedWhenClosed = false
        self.init(window: window)
        setupVisualEffect()
        observeBackdropToggle()
        clearDebugLog()
    }

    // MARK: - 调试日志

    private func clearDebugLog() {
        try? "".write(toFile: debugLogPath, atomically: true, encoding: .utf8)
    }

    private func log(_ msg: String) {
        let ts = ISO8601DateFormatter().string(from: Date())
        let line = "[\(ts)] \(msg)\n"
        if let data = line.data(using: .utf8) {
            if let handle = FileHandle(forWritingAtPath: debugLogPath) {
                handle.seekToEndOfFile()
                handle.write(data)
                handle.closeFile()
            } else {
                try? data.write(to: URL(fileURLWithPath: debugLogPath))
            }
        }
    }

    func dumpGeometry(_ tag: String) {
        guard let window = window else { return }
        log("===== \(tag) =====")
        log("window.frame          = \(window.frame)")
        log("window.styleMask      = \(window.styleMask.rawValue)")
        log("window.isOpaque       = \(window.isOpaque)")
        log("window.hasShadow      = \(window.hasShadow)")
        log("window.level          = \(window.level.rawValue)")
        log("window.backgroundColor= \(String(describing: window.backgroundColor))")
        log("window.isVisible      = \(window.isVisible)")
        log("window.titlebarAppearsTransparent = \(window.titlebarAppearsTransparent)")

        guard let cv = window.contentView else { return }
        log("--- contentView ---")
        log("contentView.frame     = \(cv.frame)")
        log("contentView.bounds    = \(cv.bounds)")
        log("contentView.subviews.count = \(cv.subviews.count)")

        for (i, sv) in cv.subviews.enumerated() {
            log("  subview[\(i)]: \(type(of: sv))")
            log("    frame       = \(sv.frame)")
            log("    bounds      = \(sv.bounds)")
            log("    isHidden    = \(sv.isHidden)")
            log("    alphaValue  = \(sv.alphaValue)")
            log("    wantsLayer  = \(sv.wantsLayer)")
            if let layer = sv.layer {
                log("    layer.frame       = \(layer.frame)")
                log("    layer.bounds      = \(layer.bounds)")
                log("    layer.cornerRadius= \(layer.cornerRadius)")
                log("    layer.masksToBounds=\(layer.masksToBounds)")
                log("    layer.isHidden    = \(layer.isHidden)")
                log("    layer.opacity     = \(layer.opacity)")
                log("    layer.sublayers?.count = \(layer.sublayers?.count ?? 0)")
                if let subs = layer.sublayers {
                    for (j, sl) in subs.enumerated() {
                        log("      sublayer[\(j)]: \(type(of: sl)) frame=\(sl.frame) bounds=\(sl.bounds) hidden=\(sl.isHidden)")
                    }
                }
            }
        }
        log("")
    }

    // MARK: - 毛玻璃背板

    private func setupVisualEffect() {
        guard let window = window else { return }

        let ve = NSVisualEffectView()
        ve.wantsLayer = true
        ve.material = .hudWindow
        ve.blendingMode = .behindWindow
        ve.state = .active
        ve.alphaValue = 1.0
        ve.translatesAutoresizingMaskIntoConstraints = false

        ve.layer?.cornerRadius = 16
        ve.layer?.masksToBounds = true
        ve.layer?.borderWidth = 0
        ve.layer?.borderColor = NSColor.clear.cgColor
        ve.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.35).cgColor

        self.visualEffect = ve

        guard let contentView = window.contentView else { return }
        contentView.addSubview(ve, positioned: .below, relativeTo: contentView.subviews.first)

        NSLayoutConstraint.activate([
            ve.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            ve.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            ve.topAnchor.constraint(equalTo: contentView.topAnchor),
            ve.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        ])

        applyBackdropEnabled(Configuration.shared.backdropEnabled)
    }

    // MARK: - 背板开关

    private func observeBackdropToggle() {
        NotificationCenter.default.addObserver(
            forName: .backdropEnabledChanged, object: nil, queue: .main
        ) { [weak self] note in
            guard let enabled = note.object as? Bool else { return }
            self?.applyBackdropEnabled(enabled)
        }
    }

    private func applyBackdropEnabled(_ enabled: Bool) {
        guard let ve = visualEffect else { return }
        guard let window = window else { return }
        if enabled {
            ve.isHidden = false
            ve.state = .active
            ve.blendingMode = .behindWindow
            ve.alphaValue = 1.0
            ve.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.35).cgColor
            window.hasShadow = true
            window.backgroundColor = .clear
        } else {
            ve.state = .inactive
            ve.blendingMode = .withinWindow
            ve.alphaValue = 1.0
            ve.layer?.backgroundColor = NSColor.clear.cgColor
            ve.isHidden = true
            window.hasShadow = false
            // 纯 clear 在部分系统上会产生窗口合成残影；使用极小 alpha 避免 Ghosting。
            window.backgroundColor = tinyAlphaBackground
        }
        window.contentView?.layerContentsRedrawPolicy = .onSetNeedsDisplay
        window.contentView?.needsDisplay = true
        window.contentView?.displayIfNeeded()
        hostingView?.layerContentsRedrawPolicy = .onSetNeedsDisplay
        hostingView?.needsDisplay = true
        hostingView?.displayIfNeeded()
        window.invalidateShadow()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
            self?.dumpGeometry("backdropEnabled=\(enabled)")
        }
    }

    func refreshAfterDataUpdate() {
        guard let window = window else { return }
        window.contentView?.needsDisplay = true
        hostingView?.needsDisplay = true
        window.displayIfNeeded()
        window.invalidateShadow()
    }

    // MARK: - SwiftUI 嵌入

    func embed(rootView: ContentView) {
        guard let window = window, let contentView = window.contentView else { return }

        let hv = NSHostingView(rootView: rootView)
        hv.wantsLayer = true
        hv.layerContentsRedrawPolicy = .onSetNeedsDisplay
        hv.layer?.cornerRadius = Configuration.shared.backdropEnabled ? 16 : 0
        hv.layer?.masksToBounds = true
        hv.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(hv)

        NSLayoutConstraint.activate([
            hv.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            hv.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            hv.topAnchor.constraint(equalTo: contentView.topAnchor),
            hv.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
        ])

        self.hostingView = hv
    }

    // MARK: - 显隐

    func toggleVisible() {
        guard let window = window else { return }
        if window.isVisible {
            window.orderOut(nil)
        } else {
            positionNearMenuBar()
            window.makeKeyAndOrderFront(nil)
            NSApp.activate(ignoringOtherApps: false)
        }
    }

    func show() {
        guard let window = window else { return }
        if !window.isVisible {
            positionNearMenuBar()
        }
        window.makeKeyAndOrderFront(nil)
        NSApp.activate(ignoringOtherApps: false)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
            self?.dumpGeometry("show")
        }
    }

    func hide() {
        window?.orderOut(nil)
    }

    var isVisible: Bool {
        window?.isVisible ?? false
    }

    // MARK: - 尺寸 & 位置

    func resize(width: CGFloat, height: CGFloat) {
        guard let window = window else { return }
        var frame = window.frame
        frame.size.width = width
        frame.size.height = height
        window.setFrame(frame, display: true, animate: true)
    }

    private func positionNearMenuBar() {
        guard let window = window, let screen = NSScreen.main else { return }
        let screenFrame = screen.visibleFrame
        window.setFrameOrigin(NSPoint(
            x: screenFrame.maxX - window.frame.width - 24,
            y: screenFrame.maxY - window.frame.height - 24
        ))
    }
}
