import SwiftUI
import AppKit

struct DesktopWidgetView: View {
    let app: LauncherApp
    let variant: WidgetVariant
    var isPreview: Bool = false
    /// Gmail: account slot for `/mail/u/{{u}}/…` in URLs. Ignored for other apps.
    var gmailAccountSlot: Int = 0

    private var actions: [WidgetAction] { variant.actions }
    private var layoutMode: WidgetLayoutMode { variant.layoutMode }
    private var showHeader: Bool { variant.showHeader }
    private var size: WidgetSize { variant.size }

    var body: some View {
        Group {
            if case .gmail(let gmailMode) = layoutMode {
                GmailDesktopWidgetView(app: app, mode: gmailMode, gmailAccountSlot: gmailAccountSlot, isPreview: isPreview)
            } else if case .drive(let driveMode) = layoutMode {
                DriveDesktopWidgetView(app: app, mode: driveMode, isPreview: isPreview)
            } else if case .keep(let keepMode) = layoutMode {
                KeepDesktopWidgetView(app: app, mode: keepMode, isPreview: isPreview)
            } else if case .translate(let translateMode) = layoutMode {
                TranslateDesktopWidgetView(app: app, mode: translateMode, isPreview: isPreview)
            } else if case .earth(let earthMode) = layoutMode {
                EarthDesktopWidgetView(app: app, mode: earthMode, isPreview: isPreview)
            } else if case .googleSearch(let searchMode) = layoutMode {
                GoogleSearchDesktopWidgetView(app: app, mode: searchMode, isPreview: isPreview)
            } else if case .calendar(let calendarMode) = layoutMode {
                CalendarDesktopWidgetView(app: app, mode: calendarMode, isPreview: isPreview)
            } else if case .books(let booksMode) = layoutMode {
                BooksDesktopWidgetView(app: app, mode: booksMode, isPreview: isPreview)
            } else if case .travel(let travelMode) = layoutMode {
                TravelDesktopWidgetView(app: app, mode: travelMode, isPreview: isPreview)
            } else if case .shopping(let shoppingMode) = layoutMode {
                ShoppingDesktopWidgetView(app: app, mode: shoppingMode, isPreview: isPreview)
            } else if case .youtube(let youtubeMode) = layoutMode {
                YouTubeDesktopWidgetView(app: app, mode: youtubeMode, isPreview: isPreview)
            } else if case .meet(let meetMode) = layoutMode {
                MeetDesktopWidgetView(app: app, mode: meetMode, isPreview: isPreview)
            } else if case .contacts(let contactsMode) = layoutMode {
                ContactsDesktopWidgetView(app: app, mode: contactsMode, isPreview: isPreview)
            } else if case .news(let newsMode) = layoutMode {
                NewsDesktopWidgetView(app: app, mode: newsMode, isPreview: isPreview)
            } else if case .forms(let formsMode) = layoutMode {
                FormsDesktopWidgetView(app: app, mode: formsMode, isPreview: isPreview)
            } else if case .docs(let docsMode) = layoutMode {
                DocsDesktopWidgetView(app: app, mode: docsMode, isPreview: isPreview)
            } else if case .sheets(let sheetsMode) = layoutMode {
                SheetsDesktopWidgetView(app: app, mode: sheetsMode, isPreview: isPreview)
            } else if case .slides(let slidesMode) = layoutMode {
                SlidesDesktopWidgetView(app: app, mode: slidesMode, isPreview: isPreview)
            } else if case .googlePlay(let playMode) = layoutMode {
                GooglePlayDesktopWidgetView(app: app, mode: playMode, isPreview: isPreview)
            } else if case .gemini(let geminiMode) = layoutMode {
                GeminiDesktopWidgetView(app: app, mode: geminiMode, isPreview: isPreview)
            } else if case .photos = layoutMode {
                PhotosDesktopWidgetView(app: app, isPreview: isPreview)
            } else if case .interactiveMap = layoutMode {
                MapsInteractiveWidgetView(app: app, widgetSize: size, isPreview: isPreview)
            } else {
                ZStack {
                    RoundedRectangle(cornerRadius: 22, style: .continuous)
                        .fill(
                            LinearGradient(
                                colors: [Color(red: 0.18, green: 0.24, blue: 0.31), Color(red: 0.18, green: 0.47, blue: 0.46)],
                                startPoint: .topLeading,
                                endPoint: .bottomTrailing
                            )
                        )
                        .shadow(color: .black.opacity(0.25), radius: 14, x: 0, y: 8)
                        .overlay(
                            RoundedRectangle(cornerRadius: 22, style: .continuous)
                                .stroke(Color.white.opacity(0.12), lineWidth: 1)
                        )

                    VStack(alignment: .leading, spacing: 12) {
                        switch layoutMode {
                        case .iconOnly(let title):
                            iconOnly(title: title)

                        case .actionsRow:
                            if showHeader {
                                header
                            }
                            rowActions(maxActions: 3)

                        case .actionsGrid(let columns):
                            if showHeader {
                                header
                            }
                            gridActions(columns: columns, maxActions: maxActionsForSize)

                        case .interactiveMap, .gmail, .drive, .keep, .translate, .earth, .googleSearch, .calendar, .books, .travel, .shopping, .youtube, .meet, .contacts, .news, .forms, .docs, .sheets, .slides, .googlePlay, .gemini, .photos:
                            EmptyView()
                        }
                    }
                    .padding(16)
                }
                .clipShape(RoundedRectangle(cornerRadius: 22, style: .continuous))
            }
        }
    }

    private var header: some View {
        HStack(spacing: 10) {
            AppIconView(app: app, size: 34, showAppBackground: false, iconPaddingFactor: 0.07)
            VStack(alignment: .leading, spacing: 2) {
                Text(app.name)
                    .font(.system(size: 16, weight: .bold))
                    .foregroundStyle(.white.opacity(0.92))
                    .lineLimit(1)
            }
            Spacer(minLength: 0)
        }
    }

    @ViewBuilder
    private func iconOnly(title: String) -> some View {
        let fontSize: CGFloat = {
            switch size {
            case .small: return 16
            case .medium: return 22
            case .large: return 18
            }
        }()

        let content = VStack(spacing: 10) {
            AppIconView(app: app, size: 44, showAppBackground: false, iconPaddingFactor: 0.05)
            Text(title)
                .font(.system(size: fontSize, weight: .bold))
                .foregroundStyle(.white.opacity(0.92))
                .lineLimit(1)
        }

        if isPreview || app.webURL == nil {
            content
        } else {
            Button(action: openBase) {
                content
            }
            .buttonStyle(.plain)
        }
    }

    private var maxActionsForSize: Int {
        switch size {
        case .small: return 3
        case .medium: return 4
        case .large: return 8
        }
    }

    private func rowActions(maxActions: Int) -> some View {
        let prefix = actions.prefix(maxActions)
        return HStack(spacing: 10) {
            ForEach(prefix) { action in
                actionChip(action: action)
            }
        }
    }

    private func gridActions(columns: Int, maxActions: Int) -> some View {
        let grid = Array(repeating: GridItem(.flexible(minimum: 0), spacing: 10), count: columns)
        return LazyVGrid(columns: grid, spacing: 10) {
            ForEach(actions.prefix(maxActions)) { action in
                actionTile(action: action)
            }
        }
    }

    private func actionChip(action: WidgetAction) -> some View {
        Button(action: { open(action: action) }) {
            HStack(spacing: 8) {
                Image(systemName: action.systemImage)
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(foregroundColor(for: action))
                Text(action.title)
                    .font(.system(size: 12, weight: .bold))
                    .foregroundStyle(foregroundColor(for: action))
                    .lineLimit(1)
            }
            .padding(.horizontal, 12)
            .padding(.vertical, 9)
            .background(
                RoundedRectangle(cornerRadius: 999, style: .continuous)
                    .fill(backgroundColor(for: action))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 999, style: .continuous)
                    .stroke(Color.white.opacity(isPrimary(action) ? 0.22 : 0.12), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
        .disabled(isPreview || app.webURL == nil)
        // In the widget picker, we want clicks to toggle the whole card.
        // Ensure preview buttons do not intercept hit testing.
        .allowsHitTesting(!(isPreview || app.webURL == nil))
        .opacity((isPreview || app.webURL == nil) ? 0.6 : 1)
    }

    private func actionTile(action: WidgetAction) -> some View {
        Button(action: { open(action: action) }) {
            HStack(spacing: 10) {
                Image(systemName: action.systemImage)
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(foregroundColor(for: action))
                Text(action.title)
                    .font(.system(size: 12, weight: .bold))
                    .foregroundStyle(foregroundColor(for: action))
                    .lineLimit(1)
                Spacer(minLength: 0)
            }
            .padding(.horizontal, 12)
            .padding(.vertical, 10)
            .background(
                RoundedRectangle(cornerRadius: 14, style: .continuous)
                    .fill(backgroundColor(for: action))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 14, style: .continuous)
                    .stroke(Color.white.opacity(isPrimary(action) ? 0.22 : 0.12), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
        .disabled(isPreview || app.webURL == nil)
        // In the widget picker, we want clicks to toggle the whole card.
        // Ensure preview buttons do not intercept hit testing.
        .allowsHitTesting(!(isPreview || app.webURL == nil))
        .opacity((isPreview || app.webURL == nil) ? 0.6 : 1)
    }

    private func openBase() {
        guard !isPreview, let url = app.webURL else { return }
        InAppBrowserWindowManager.shared.open(url: url, title: app.name)
    }

    private func open(action: WidgetAction) {
        guard !isPreview, let base = app.webURL else { return }
        let target = WidgetDeepLinkURL.resolved(base: base, actionPath: action.urlPath, accountSlot: gmailAccountSlot)
        if target.scheme?.lowercased() == "mailto" {
            NSWorkspace.shared.open(target)
        } else {
            InAppBrowserWindowManager.shared.open(url: target, title: app.name)
        }
    }

    private func isPrimary(_ action: WidgetAction) -> Bool {
        actions.first?.id == action.id
    }

    private func backgroundColor(for action: WidgetAction) -> Color {
        isPrimary(action) ? Color.white.opacity(0.38) : Color.black.opacity(0.66)
    }

    private func foregroundColor(for action: WidgetAction) -> Color {
        isPrimary(action) ? Color.white.opacity(0.95) : Color.white.opacity(0.88)
    }
}

