import AppKit
import Combine
import SwiftUI
import WebKit

/// Holds the embedded Google Earth `WKWebView` and last loaded URL for `NSViewRepresentable` updates.
private final class EarthWebViewRef: ObservableObject {
    weak var webView: WKWebView?
    var lastLoadedURLString: String?
}

/// Large interactive Google Earth Web: full globe in an embedded web view with an open-in-browser control.
struct EarthDesktopWidgetView: View {
    let app: LauncherApp
    let mode: EarthWidgetMode
    var isPreview: Bool = false

    @StateObject private var webRef = EarthWebViewRef()
    @State private var webURL: URL

    private var baseURL: URL { app.webURL ?? URL(string: "https://earth.google.com")! }

    init(app: LauncherApp, mode: EarthWidgetMode, isPreview: Bool = false) {
        self.app = app
        self.mode = mode
        self.isPreview = isPreview
        let base = app.webURL ?? URL(string: "https://earth.google.com")!
        _webURL = State(
            initialValue: WidgetDeepLinkURL.resolved(base: base, actionPath: "/web/", accountSlot: 0)
        )
    }

    var body: some View {
        Group {
            switch mode {
            case .interactive:
                interactiveBody
            }
        }
        .clipShape(RoundedRectangle(cornerRadius: 22, style: .continuous))
    }

    private var interactiveBody: some View {
        Group {
            if isPreview {
                earthPreviewChrome
            } else {
                earthLiveChrome
            }
        }
    }

    private var earthPreviewChrome: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(
                    LinearGradient(
                        colors: [Color(red: 0.1, green: 0.35, blue: 0.65), Color(red: 0.02, green: 0.12, blue: 0.28)],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
            VStack(spacing: 12) {
                AppIconView(app: app, size: 48, showAppBackground: false, iconPaddingFactor: 0.08)
                Text("Google Earth")
                    .font(.system(size: 15, weight: .bold))
                    .foregroundStyle(.white.opacity(0.92))
                Text("Explore the full globe inside this widget, or open Earth in your browser.")
                    .font(.system(size: 11, weight: .medium))
                    .foregroundStyle(.white.opacity(0.7))
                    .multilineTextAlignment(.center)
                    .padding(.horizontal, 8)
            }
            .padding(16)
        }
    }

    private var earthLiveChrome: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(Color.black.opacity(0.24))

            VStack(spacing: 0) {
                earthToolbar
                EarthWebWidgetView(url: $webURL, webRef: webRef)
                    .frame(minHeight: 340)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
            }
            .padding(10)
        }
    }

    private var earthToolbar: some View {
        HStack(spacing: 8) {
            AppIconView(app: app, size: 28, showAppBackground: false, iconPaddingFactor: 0.08)
            Text("Earth")
                .font(.system(size: 14, weight: .bold))
                .foregroundStyle(.white.opacity(0.95))
            Spacer(minLength: 0)
            Button(action: {
                NSApp.activate(ignoringOtherApps: true)
                openInAppBrowser(baseURL)
            }) {
                Image(systemName: "arrow.up.right.square")
                    .font(.system(size: 13, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.9))
                    .padding(8)
                    .background(Circle().fill(Color.white.opacity(0.12)))
            }
            .buttonStyle(.plain)
            .help("Open Earth in browser")
        }
        .padding(.horizontal, 6)
        .padding(.vertical, 8)
        .background(
            RoundedRectangle(cornerRadius: 16, style: .continuous)
                .fill(Color(red: 0.04, green: 0.1, blue: 0.22))
        )
        .zIndex(20)
    }

    private func openInAppBrowser(_ url: URL) {
        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
    }
}

// MARK: - WKWebView

private final class EarthWebViewClippingContainer: NSView {
    override var isFlipped: Bool { true }
}

private struct EarthWebWidgetView: NSViewRepresentable {
    @Binding var url: URL
    var webRef: EarthWebViewRef

    func makeCoordinator() -> Coordinator {
        Coordinator(webRef: webRef)
    }

    func makeNSView(context: Context) -> NSView {
        let container = EarthWebViewClippingContainer()
        container.wantsLayer = true
        container.layer?.masksToBounds = true
        container.layer?.cornerRadius = 12

        let config = WKWebViewConfiguration()
        config.defaultWebpagePreferences.allowsContentJavaScript = true
        let wv = WKWebView(frame: .zero, configuration: config)
        wv.translatesAutoresizingMaskIntoConstraints = false
        wv.focusRingType = .none
        wv.customUserAgent =
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15"
        wv.navigationDelegate = context.coordinator

        container.addSubview(wv)
        NSLayoutConstraint.activate([
            wv.leadingAnchor.constraint(equalTo: container.leadingAnchor),
            wv.trailingAnchor.constraint(equalTo: container.trailingAnchor),
            wv.topAnchor.constraint(equalTo: container.topAnchor),
            wv.bottomAnchor.constraint(equalTo: container.bottomAnchor),
        ])

        context.coordinator.webView = wv
        webRef.webView = wv
        webRef.lastLoadedURLString = url.absoluteString
        wv.load(URLRequest(url: url))
        DispatchQueue.main.async {
            Self.stripWebKitOuterChrome(wv)
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
            Self.stripWebKitOuterChrome(wv)
        }
        return container
    }

    func updateNSView(_ container: NSView, context: Context) {
        guard let wv = context.coordinator.webView else { return }
        let next = url.absoluteString
        if webRef.lastLoadedURLString == next { return }
        webRef.lastLoadedURLString = next
        wv.load(URLRequest(url: url))
    }

    private static func stripWebKitOuterChrome(_ webView: WKWebView) {
        webView.focusRingType = .none
        func walk(_ view: NSView) {
            view.focusRingType = .none
            view.layer?.borderWidth = 0
            view.layer?.borderColor = NSColor.clear.cgColor
            if let scroll = view as? NSScrollView {
                scroll.borderType = .noBorder
                scroll.drawsBackground = false
                scroll.scrollerStyle = .overlay
            }
            if let clip = view as? NSClipView {
                clip.drawsBackground = false
            }
            for sub in view.subviews {
                walk(sub)
            }
        }
        walk(webView)
    }

    final class Coordinator: NSObject, WKNavigationDelegate {
        weak var webView: WKWebView?
        let webRef: EarthWebViewRef

        init(webRef: EarthWebViewRef) {
            self.webRef = webRef
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            self.webView = webView
            webRef.webView = webView
            EarthWebWidgetView.stripWebKitOuterChrome(webView)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.12) {
                EarthWebWidgetView.stripWebKitOuterChrome(webView)
            }
        }
    }
}
