import AppKit
import SwiftUI

private let newsPanelBackground = Color(red: 0.07, green: 0.09, blue: 0.12)
private let newsAccent = Color(red: 0.26, green: 0.52, blue: 0.96)

/// Google News: medium = search + top headlines; large = search + topic shortcuts + “Picks for You”.
/// Story taps open Google News search for that headline (full coverage) in the in-app browser.
struct NewsDesktopWidgetView: View {
    let app: LauncherApp
    let mode: NewsWidgetMode
    var isPreview: Bool = false

    @State private var searchText: String = ""

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

    var body: some View {
        Group {
            switch mode {
            case .headlines:
                headlinesRoot
            case .picksHub:
                picksHubRoot
            }
        }
        .clipShape(RoundedRectangle(cornerRadius: 22, style: .continuous))
    }

    // MARK: - Medium

    private var headlinesRoot: some View {
        Group {
            if isPreview {
                newsPreviewChrome(
                    title: "Headlines & search",
                    subtitle: "Search the news and browse top headlines; stories open in Google News."
                )
            } else {
                headlinesLive
            }
        }
    }

    private var headlinesLive: some View {
        VStack(alignment: .leading, spacing: 10) {
            newsHeaderRow(showRefresh: false)

            newsSearchRow

            Text("Top headlines")
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.white.opacity(0.45))
                .textCase(.uppercase)

            ScrollView {
                VStack(alignment: .leading, spacing: 6) {
                    ForEach(Self.topHeadlines) { item in
                        headlineButton(item)
                    }
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .frame(maxHeight: .infinity)
        }
        .padding(14)
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .background(
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(newsPanelBackground)
        )
        .preferredColorScheme(.dark)
    }

    // MARK: - Large

    private var picksHubRoot: some View {
        Group {
            if isPreview {
                newsPreviewChrome(
                    title: "Picks & topics",
                    subtitle: "Search, jump to topics, and open stories from Picks for You."
                )
            } else {
                picksHubLive
            }
        }
    }

    private var picksHubLive: some View {
        VStack(alignment: .leading, spacing: 10) {
            newsHeaderRow(showRefresh: true)

            newsSearchRow

            Text("Topics")
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.white.opacity(0.45))
                .textCase(.uppercase)

            LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 8) {
                newsTopicPill(title: "World", systemImage: "globe.americas.fill", query: "World news")
                newsTopicPill(title: "Local", systemImage: "mappin.and.ellipse", query: "Local news")
                newsTopicPill(title: "Business", systemImage: "briefcase.fill", query: "Business news")
                newsTopicPill(title: "Technology", systemImage: "cpu", query: "Technology news")
            }

            Text("Picks for you")
                .font(.system(size: 10, weight: .bold))
                .foregroundStyle(.white.opacity(0.45))
                .textCase(.uppercase)
                .padding(.top, 2)

            ScrollView {
                VStack(alignment: .leading, spacing: 6) {
                    ForEach(Self.picksForYou) { item in
                        pickRowButton(item)
                    }
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .frame(maxHeight: .infinity)
        }
        .padding(14)
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
        .background(
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(newsPanelBackground)
        )
        .preferredColorScheme(.dark)
    }

    // MARK: - Shared pieces

    private func newsHeaderRow(showRefresh: Bool) -> some View {
        HStack(spacing: 8) {
            AppIconView(app: app, size: 28, showAppBackground: false, iconPaddingFactor: 0.08)
            Text("Google News")
                .font(.system(size: 14, weight: .bold))
                .foregroundStyle(.white.opacity(0.95))
            Spacer(minLength: 0)
            if showRefresh {
                Button(action: { openNewsPath("/topstories") }) {
                    Image(systemName: "arrow.clockwise")
                        .font(.system(size: 13, weight: .semibold))
                        .foregroundStyle(.white.opacity(0.9))
                        .padding(8)
                        .background(Circle().fill(Color.white.opacity(0.1)))
                }
                .buttonStyle(.plain)
                .help("Open Headlines in Google News")
            }
            Button(action: { 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.1)))
            }
            .buttonStyle(.plain)
            .help("Open Google News")
        }
    }

    private var newsSearchRow: some View {
        HStack(spacing: 8) {
            TextField("Search news", text: $searchText)
                .textFieldStyle(.plain)
                .font(.system(size: 13, weight: .medium))
                .padding(.horizontal, 12)
                .padding(.vertical, 8)
                .background(
                    RoundedRectangle(cornerRadius: 12, style: .continuous)
                        .fill(Color.white.opacity(0.1))
                )
                .foregroundStyle(.white.opacity(0.95))
                .onSubmit { submitSearch() }
            Button("Search", action: submitSearch)
                .font(.system(size: 12, weight: .semibold))
                .buttonStyle(.borderedProminent)
                .tint(newsAccent)
                .controlSize(.regular)
        }
    }

    private func headlineButton(_ item: NewsStoryItem) -> some View {
        Button {
            openStory(title: item.title)
        } label: {
            VStack(alignment: .leading, spacing: 4) {
                Text(item.title)
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.95))
                    .multilineTextAlignment(.leading)
                    .lineLimit(3)
                if let meta = item.meta {
                    Text(meta)
                        .font(.system(size: 10, weight: .medium))
                        .foregroundStyle(.white.opacity(0.45))
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(10)
            .background(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .fill(Color.white.opacity(0.06))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .strokeBorder(Color.white.opacity(0.06), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
    }

    private func pickRowButton(_ item: NewsStoryItem) -> some View {
        headlineButton(item)
    }

    private func newsTopicPill(title: String, systemImage: String, query: String) -> some View {
        Button {
            openNewsSearch(query: query)
        } label: {
            HStack(spacing: 8) {
                Image(systemName: systemImage)
                    .font(.system(size: 14, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.88))
                Text(title)
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.9))
                    .lineLimit(1)
                Spacer(minLength: 0)
            }
            .padding(.horizontal, 10)
            .padding(.vertical, 10)
            .background(
                RoundedRectangle(cornerRadius: 14, style: .continuous)
                    .fill(Color.white.opacity(0.08))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 14, style: .continuous)
                    .strokeBorder(Color.white.opacity(0.06), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
    }

    private func newsPreviewChrome(title: String, subtitle: String) -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(
                    LinearGradient(
                        colors: [newsAccent.opacity(0.75), newsPanelBackground],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
            VStack(spacing: 12) {
                AppIconView(app: app, size: 48, showAppBackground: false, iconPaddingFactor: 0.08)
                Text(title)
                    .font(.system(size: 15, weight: .bold))
                    .foregroundStyle(.white.opacity(0.95))
                Text(subtitle)
                    .font(.system(size: 11, weight: .medium))
                    .foregroundStyle(.white.opacity(0.75))
                    .multilineTextAlignment(.center)
                    .padding(.horizontal, 8)
            }
            .padding(16)
        }
    }

    // MARK: - URLs

    private func submitSearch() {
        let q = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !q.isEmpty else { return }
        openNewsSearch(query: q)
    }

    private func openStory(title: String) {
        openNewsSearch(query: title)
    }

    private func openNewsSearch(query: String) {
        let q = query.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !q.isEmpty else { return }
        NSApp.activate(ignoringOtherApps: true)
        guard var c = URLComponents(url: baseURL, resolvingAgainstBaseURL: false) else { return }
        c.path = "/search"
        c.queryItems = [
            URLQueryItem(name: "q", value: q),
            URLQueryItem(name: "hl", value: "en-US"),
            URLQueryItem(name: "gl", value: "US"),
            URLQueryItem(name: "ceid", value: "US:en"),
        ]
        if let url = c.url {
            openInAppBrowser(url)
        }
    }

    private func openNewsPath(_ path: String) {
        NSApp.activate(ignoringOtherApps: true)
        let url = WidgetDeepLinkURL.resolved(base: baseURL, actionPath: path, accountSlot: 0)
        openInAppBrowser(url)
    }

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

    // MARK: - Sample content (offline; mirrors typical Home feed)

    private struct NewsStoryItem: Identifiable {
        let id: String
        let title: String
        let meta: String?
    }

    private static let topHeadlines: [NewsStoryItem] = [
        NewsStoryItem(id: "h1", title: "Central banks signal cautious stance as markets digest inflation data", meta: "Reuters · 2h"),
        NewsStoryItem(id: "h2", title: "Tech giants outline AI safety commitments ahead of global summit", meta: "AP News · 3h"),
        NewsStoryItem(id: "h3", title: "Regional cities see renewed investment in public transit projects", meta: "Bloomberg · 4h"),
        NewsStoryItem(id: "h4", title: "Healthcare sector weighs new guidelines for seasonal care", meta: "The Guardian · 5h"),
        NewsStoryItem(id: "h5", title: "Sports leagues expand streaming partnerships for international fans", meta: "ESPN · 6h"),
    ]

    private static let picksForYou: [NewsStoryItem] = [
        NewsStoryItem(id: "p1", title: "Why urban planners are prioritizing walkable neighborhoods in 2026", meta: "For you · Science & climate"),
        NewsStoryItem(id: "p2", title: "Startups bet on smaller, more efficient chips for edge devices", meta: "For you · Tech"),
        NewsStoryItem(id: "p3", title: "What changing interest rates could mean for first-time buyers", meta: "For you · Business"),
        NewsStoryItem(id: "p4", title: "Five destinations seeing a surge in off-season travel", meta: "For you · World"),
        NewsStoryItem(id: "p5", title: "New studies explore sleep habits and weekday productivity", meta: "For you · Health"),
    ]
}
