import AppKit
import SwiftUI
import WebKit

// MARK: - Public SwiftUI view

/// Tiered Gmail desktop widget: compact unread + compose, or full embedded Gmail.
struct GmailDesktopWidgetView: View {
    let app: LauncherApp
    let mode: GmailWidgetMode
    var gmailAccountSlot: Int = 0
    var isPreview: Bool = false

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

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

    // MARK: - Compact (small)

    @AppStorage("gmailDesktopWidgetUnreadCount") private var unreadCountStored: Int = -1

    private var compactBody: some View {
        ZStack(alignment: .topLeading) {
            gmailGradientBackground
                .frame(maxWidth: .infinity, maxHeight: .infinity)
            VStack(alignment: .leading, spacing: 10) {
                HStack(spacing: 10) {
                    AppIconView(app: app, size: 32, showAppBackground: false, iconPaddingFactor: 0.08)
                    VStack(alignment: .leading, spacing: 2) {
                        Text(app.name)
                            .font(.system(size: 14, weight: .bold))
                            .foregroundStyle(.white.opacity(0.95))
                        Text("Unread")
                            .font(.system(size: 10, weight: .semibold))
                            .foregroundStyle(.white.opacity(0.65))
                    }
                    Spacer(minLength: 0)
                }

                HStack(alignment: .firstTextBaseline, spacing: 6) {
                    Text(unreadCountStored < 0 ? "—" : "\(unreadCountStored)")
                        .font(.system(size: 36, weight: .bold, design: .rounded))
                        .foregroundStyle(.white)
                        .minimumScaleFactor(0.5)
                        .lineLimit(1)
                    Text("messages")
                        .font(.system(size: 11, weight: .medium))
                        .foregroundStyle(.white.opacity(0.7))
                    Spacer(minLength: 0)
                }

                Text("Local count only — use Open Mail for your live inbox.")
                    .font(.system(size: 9, weight: .medium))
                    .foregroundStyle(.white.opacity(0.52))
                    .lineLimit(2)
                    .fixedSize(horizontal: false, vertical: true)

                compactButton(title: "Open Mail", systemImage: "envelope.open", emphasized: false) {
                    openMailInBrowser()
                }

                HStack(spacing: 8) {
                    compactButton(title: "Compose", systemImage: "square.and.pencil", emphasized: true) {
                        openCompose()
                    }
                    compactButton(title: "Unread", systemImage: "envelope.badge", emphasized: false) {
                        openUnreadSearch()
                    }
                }
            }
            .padding(14)
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .disabled(isPreview)
        .opacity(isPreview ? 0.85 : 1)
    }

    // MARK: - Large (interactive)

    @State private var searchText = ""
    @State private var webURL: URL

    init(app: LauncherApp, mode: GmailWidgetMode, gmailAccountSlot: Int = 0, isPreview: Bool = false) {
        self.app = app
        self.mode = mode
        self.gmailAccountSlot = gmailAccountSlot
        self.isPreview = isPreview
        let base = app.webURL ?? URL(string: "https://mail.google.com")!
        _webURL = State(initialValue: Self.defaultInboxURL(base: base, slot: gmailAccountSlot))
    }

    private static func defaultInboxURL(base: URL, slot: Int) -> URL {
        WidgetDeepLinkURL.resolved(base: base, actionPath: "/mail/u/{{u}}/#inbox", accountSlot: slot)
    }

    private var interactiveBody: some View {
        Group {
            if isPreview {
                interactivePreviewChrome
            } else {
                interactiveLiveChrome
            }
        }
    }

    private var interactivePreviewChrome: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(
                    LinearGradient(
                        colors: [Color(red: 0.32, green: 0.14, blue: 0.12), Color(red: 0.12, green: 0.14, blue: 0.2)],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
            VStack(spacing: 12) {
                AppIconView(app: app, size: 48, showAppBackground: false, iconPaddingFactor: 0.08)
                Text("Gmail inbox")
                    .font(.system(size: 15, weight: .bold))
                    .foregroundStyle(.white.opacity(0.92))
                Text("Full inbox, search, and folder shortcuts load on your desktop.")
                    .font(.system(size: 11, weight: .medium))
                    .foregroundStyle(.white.opacity(0.65))
                    .multilineTextAlignment(.center)
                    .padding(.horizontal, 8)
            }
            .padding(16)
        }
    }

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

            VStack(spacing: 0) {
                VStack(spacing: 8) {
                    interactiveHeader
                    interactiveSearchBar
                    smartShortcutsRow
                    folderShortcutsRow
                }
                .padding(.horizontal, 6)
                .padding(.vertical, 8)
                .background(
                    RoundedRectangle(cornerRadius: 16, style: .continuous)
                        .fill(Color(red: 0.07, green: 0.08, blue: 0.1))
                )
                .zIndex(20)
                .allowsHitTesting(true)

                GmailWebWidgetView(url: $webURL)
                    .frame(minHeight: 280)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
                    .zIndex(0)
            }
            .padding(10)
        }
    }

    private var interactiveHeader: some View {
        HStack(spacing: 8) {
            AppIconView(app: app, size: 28, showAppBackground: false, iconPaddingFactor: 0.08)
            Text("Gmail")
                .font(.system(size: 14, weight: .bold))
                .foregroundStyle(.white.opacity(0.95))
            Spacer(minLength: 0)
            Button(action: {
                NSApp.activate(ignoringOtherApps: true)
                openMailInBrowser()
            }) {
                Image(systemName: "envelope.open")
                    .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 Mail in app browser")
            Button(action: {
                NSApp.activate(ignoringOtherApps: true)
                openCompose()
            }) {
                Image(systemName: "square.and.pencil")
                    .font(.system(size: 13, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.9))
                    .padding(8)
                    .background(Circle().fill(Color.white.opacity(0.12)))
            }
            .buttonStyle(.plain)
            .help("Compose")
        }
    }

    private var interactiveSearchBar: some View {
        HStack(spacing: 8) {
            Image(systemName: "magnifyingglass")
                .font(.system(size: 12, weight: .semibold))
                .foregroundStyle(.white.opacity(0.55))
            TextField("Search mail", text: $searchText)
                .textFieldStyle(.plain)
                .font(.system(size: 12, weight: .medium))
                .foregroundStyle(.white.opacity(0.95))
                .onSubmit { submitSearch() }
            Button("Go") {
                submitSearch()
            }
            .font(.system(size: 11, weight: .bold))
            .foregroundStyle(Color(red: 0.95, green: 0.45, blue: 0.35))
            .buttonStyle(.plain)
        }
        .padding(.horizontal, 10)
        .padding(.vertical, 8)
        .background(
            RoundedRectangle(cornerRadius: 10, style: .continuous)
                .fill(Color.white.opacity(0.08))
        )
    }

    private var smartShortcutsRow: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 8) {
                shortcutChip("Primary", fragment: "#category/primary")
                shortcutChip("Social", fragment: "#category/social")
                shortcutChip("Promotions", fragment: "#category/promotions")
                shortcutChip("Updates", fragment: "#category/updates")
                shortcutChip("Forums", fragment: "#category/forums")
            }
        }
    }

    private var folderShortcutsRow: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 8) {
                shortcutChip("Inbox", fragment: "#inbox")
                shortcutChip("Starred", fragment: "#starred")
                shortcutChip("Snoozed", fragment: "#snoozed")
                shortcutChip("Sent", fragment: "#sent")
                shortcutChip("Drafts", fragment: "#drafts")
                shortcutChip("All Mail", fragment: "#all")
                shortcutChip("Spam", fragment: "#spam")
                shortcutChip("Trash", fragment: "#trash")
            }
        }
    }

    private func shortcutChip(_ title: String, fragment: String) -> some View {
        Button(action: {
            NSApp.activate(ignoringOtherApps: true)
            navigateToMailPath("/mail/u/{{u}}/\(fragment)")
        }) {
            Text(title)
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.white.opacity(0.92))
                .padding(.horizontal, 10)
                .padding(.vertical, 6)
                .background(Capsule().fill(Color.white.opacity(0.12)))
                .overlay(Capsule().stroke(Color.white.opacity(0.14), lineWidth: 1))
        }
        .buttonStyle(.plain)
    }

    // MARK: - Shared chrome

    private var gmailGradientBackground: some View {
        LinearGradient(
            colors: [
                Color(red: 0.42, green: 0.2, blue: 0.18),
                Color(red: 0.14, green: 0.18, blue: 0.26),
            ],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
    }

    private func compactButton(title: String, systemImage: String, emphasized: Bool, action: @escaping () -> Void) -> some View {
        Button(action: {
            NSApp.activate(ignoringOtherApps: true)
            action()
        }) {
            HStack(spacing: 6) {
                Image(systemName: systemImage)
                    .font(.system(size: 12, weight: .semibold))
                Text(title)
                    .font(.system(size: 12, weight: .bold))
            }
            .foregroundStyle(emphasized ? Color(red: 0.12, green: 0.12, blue: 0.14) : .white.opacity(0.92))
            .frame(maxWidth: .infinity)
            .padding(.vertical, 10)
            .background(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .fill(emphasized ? Color.white.opacity(0.92) : Color.black.opacity(0.35))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .stroke(Color.white.opacity(emphasized ? 0.35 : 0.14), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
    }

    // MARK: - Navigation

    private func openMailInBrowser() {
        guard !isPreview else { return }
        let url = WidgetDeepLinkURL.resolved(
            base: baseURL,
            actionPath: "/mail/u/{{u}}/#inbox",
            accountSlot: gmailAccountSlot
        )
        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
    }

    private func openCompose() {
        guard !isPreview else { return }
        let url = WidgetDeepLinkURL.resolved(
            base: baseURL,
            actionPath: "/mail/u/{{u}}/#inbox?compose=new",
            accountSlot: gmailAccountSlot
        )
        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
    }

    private func openUnreadSearch() {
        guard !isPreview else { return }
        let url = WidgetDeepLinkURL.resolved(
            base: baseURL,
            actionPath: "/mail/u/{{u}}/#search/is:unread",
            accountSlot: gmailAccountSlot
        )
        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
    }

    private func navigateToMailPath(_ path: String) {
        let url = WidgetDeepLinkURL.resolved(base: baseURL, actionPath: path, accountSlot: gmailAccountSlot)
        DispatchQueue.main.async {
            webURL = url
        }
    }

    private func submitSearch() {
        let q = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !q.isEmpty else { return }
        let encoded = q.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed) ?? q
        navigateToMailPath("/mail/u/{{u}}/#search/\(encoded)")
    }
}

// MARK: - WKWebView

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

private struct GmailWebWidgetView: NSViewRepresentable {
    @Binding var url: URL

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

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

        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
        context.coordinator.lastLoadedURLString = url.absoluteString
        wv.load(URLRequest(url: url))
        DispatchQueue.main.async {
            Self.stripWebKitOuterChrome(wv)
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
            Self.stripWebKitOuterChrome(wv)
        }
        return container
    }

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

    /// WebKit embeds an `NSScrollView` that often draws a 1pt dark border around the web area (visible on large widgets).
    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?
        var lastLoadedURLString: String?

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            GmailWebWidgetView.stripWebKitOuterChrome(webView)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
                GmailWebWidgetView.stripWebKitOuterChrome(webView)
            }
        }
    }
}
