import SwiftUI
import AppKit

struct DesktopWidgetView: View {
    let variant: WidgetVariant
    var isPreview: Bool
    private let authService = GoogleOAuthService.shared

    private var isSignedIn: Bool {
        if isPreview { return true }
        return authService.loadTokens() != nil
    }

    private var topMeetings: [WidgetMeetingSnapshot] {
        WidgetMeetingStore.load().prefix(3).map { $0 }
    }

    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 22, style: .continuous)
                .fill(
                    LinearGradient(
                        colors: [
                            Color(red: 0.08, green: 0.48, blue: 0.86),
                            Color(red: 0.09, green: 0.66, blue: 0.46)
                        ],
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    )
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 22, style: .continuous)
                        .stroke(Color.white.opacity(0.14), lineWidth: 1)
                )

            VStack(alignment: .leading, spacing: 12) {
                widgetHeader
                contentBody
                if variant.size != .small {
                    Spacer(minLength: 0)
                }
            }
            .padding(.horizontal, 14)
            .padding(.bottom, variant.size == .medium ? 16 : 14)
            .padding(.top, variant.size == .medium ? 18 : 10)
        }
    }

    @ViewBuilder
    private var contentBody: some View {
        switch variant.size {
        case .small:
            VStack(alignment: .leading, spacing: 10) {
                Text("Quick actions")
                    .font(.system(size: 11.5, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.78))
                compactActionButton(title: "Open Meet", icon: "video.fill", destination: .joinMeetings)
                HStack(spacing: 8) {
                    compactActionButton(title: "Schedule", icon: "clock.badge.checkmark", destination: .schedule)
                    compactActionButton(title: "Settings", icon: "gearshape.fill", destination: .settings)
                }
            }
        case .medium:
            meetingBlock(maxRows: 2)
            LazyVGrid(columns: Array(repeating: GridItem(.flexible(minimum: 0), spacing: 8), count: 2), spacing: 8) {
                ForEach(variant.quickActions.prefix(4)) { action in
                    actionTile(action)
                }
            }
        }
    }

    private var widgetHeader: some View {
        HStack(spacing: 10) {
            Image("HeaderLogo")
                .resizable()
                .scaledToFit()
                .frame(width: 30, height: 30)
                .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
            VStack(alignment: .leading, spacing: 2) {
                Text(variant.title)
                    .font(.system(size: 16, weight: .bold))
                    .foregroundStyle(.white.opacity(0.95))
                Text(variant.subtitle)
                    .font(.system(size: 12, weight: .medium))
                    .foregroundStyle(.white.opacity(0.8))
            }
            Spacer(minLength: 0)
        }
    }

    private func meetingBlock(maxRows: Int) -> some View {
        VStack(alignment: .leading, spacing: 9) {
            Text("Upcoming meetings")
                .font(.system(size: 11.5, weight: .semibold))
                .foregroundStyle(.white.opacity(0.80))
            if !isSignedIn {
                signInCTA
            } else if topMeetings.isEmpty {
                Text("No upcoming meetings")
                    .font(.system(size: 12, weight: .medium))
                    .foregroundStyle(.white.opacity(0.82))
            } else {
                VStack(alignment: .leading, spacing: 8) {
                    ForEach(topMeetings.prefix(maxRows)) { meeting in
                        meetingRow(meeting)
                    }
                }
            }
        }
    }

    private var signInCTA: some View {
        VStack(alignment: .leading, spacing: 10) {
            Text("Sign in to see upcoming meetings")
                .font(.system(size: 12, weight: .medium))
                .foregroundStyle(.white.opacity(0.86))

            Button(action: { WidgetAppNavigator.open(target: .signIn) }) {
                HStack(spacing: 8) {
                    Image(systemName: "person.crop.circle.badge.checkmark")
                        .font(.system(size: 12, weight: .semibold))
                    Text("Sign in with Google")
                        .font(.system(size: 12.5, weight: .bold))
                    Spacer(minLength: 0)
                }
                .foregroundStyle(.white.opacity(0.95))
                .padding(.horizontal, 12)
                .padding(.vertical, 10)
                .background(
                    RoundedRectangle(cornerRadius: 12, style: .continuous)
                        .fill(Color.black.opacity(0.24))
                )
                .overlay(
                    RoundedRectangle(cornerRadius: 12, style: .continuous)
                        .stroke(Color.white.opacity(0.16), lineWidth: 1)
                )
            }
            .buttonStyle(.plain)
            .disabled(isPreview)
            .allowsHitTesting(!isPreview)
        }
    }

    private func meetingRow(_ meeting: WidgetMeetingSnapshot) -> some View {
        Button(action: {
            if let link = meeting.joinLink?.trimmingCharacters(in: .whitespacesAndNewlines), !link.isEmpty {
                WidgetAppNavigator.openMeetingLink(link)
            } else {
                WidgetAppNavigator.open(target: .schedule)
            }
        }) {
            HStack(spacing: 8) {
                Image(systemName: "video.fill")
                    .font(.system(size: 11, weight: .semibold))
                    .foregroundStyle(.white.opacity(0.88))
                VStack(alignment: .leading, spacing: 1) {
                    Text(meeting.title)
                        .font(.system(size: 11.5, weight: .semibold))
                        .foregroundStyle(.white.opacity(0.93))
                        .lineLimit(1)
                    Text(meeting.timeText)
                        .font(.system(size: 10.5, weight: .medium))
                        .foregroundStyle(.white.opacity(0.74))
                        .lineLimit(1)
                }
                Spacer(minLength: 0)
            }
            .padding(.horizontal, 10)
            .padding(.vertical, 7)
            .background(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .fill(Color.black.opacity(0.20))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .stroke(Color.white.opacity(0.08), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
        .disabled(isPreview)
        .allowsHitTesting(!isPreview)
    }

    private func compactActionButton(title: String, icon: String, destination: WidgetQuickAction.Destination) -> some View {
        Button(action: { WidgetAppNavigator.open(target: destination) }) {
            HStack(spacing: 5) {
                Image(systemName: icon)
                    .font(.system(size: 10.5, weight: .semibold))
                    .frame(width: 14)
                Text(title)
                    .font(.system(size: 11.5, weight: .bold))
                    .lineLimit(1)
                    .minimumScaleFactor(0.82)
                    .layoutPriority(1)
            }
            .foregroundStyle(.white.opacity(0.97))
            .padding(.horizontal, 10)
            .padding(.vertical, 8)
            .frame(maxWidth: .infinity)
            .background(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .fill(Color.black.opacity(0.30))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .stroke(Color.white.opacity(0.24), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
        .disabled(isPreview)
        .allowsHitTesting(!isPreview)
    }

    private func actionTile(_ action: WidgetQuickAction) -> some View {
        Button(action: { open(action: action) }) {
            HStack(spacing: 8) {
                Image(systemName: action.systemImage)
                    .font(.system(size: 11, weight: .semibold))
                Text(action.title)
                    .font(.system(size: 12, weight: .bold))
                    .lineLimit(1)
                Spacer(minLength: 0)
            }
            .foregroundStyle(.white.opacity(0.92))
            .padding(.horizontal, 10)
            .padding(.vertical, 9)
            .background(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .fill(Color.black.opacity(0.24))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .stroke(Color.white.opacity(0.10), lineWidth: 1)
            )
        }
        .buttonStyle(.plain)
        .disabled(isPreview)
        .allowsHitTesting(!isPreview)
    }

    private func open(action: WidgetQuickAction) {
        guard !isPreview else { return }
        WidgetAppNavigator.open(target: action.destination)
    }
}

struct WidgetMeetingSnapshot: Codable, Identifiable {
    let id: String
    let title: String
    let timeText: String
    let joinLink: String?
}

enum WidgetMeetingStore {
    static let key = "meetings.widget.topMeetings"

    static func load() -> [WidgetMeetingSnapshot] {
        guard let data = UserDefaults.standard.data(forKey: key) else { return [] }
        return (try? JSONDecoder().decode([WidgetMeetingSnapshot].self, from: data)) ?? []
    }
}

enum WidgetAppNavigator {
    static func open(target: WidgetQuickAction.Destination) {
        DispatchQueue.main.async {
            if target == .refreshMeetings {
                postTarget(target, delay: 0)
                return
            }
            if target == .signIn {
                postTarget(target, delay: 0)
                return
            }

            bringAppToFront()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.18) {
                bringAppToFront()
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.42) {
                bringAppToFront()
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.60) {
                activateApplicationFallback()
                bringAppToFront()
            }
            postTarget(target, delay: 0.30)
        }
    }

    static func openMeetingLink(_ link: String) {
        DispatchQueue.main.async {
            bringAppToFront()
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.20) {
                bringAppToFront()
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.36) {
                NotificationCenter.default.post(
                    name: .widgetOpenMeetingLinkRequested,
                    object: nil,
                    userInfo: ["link": link]
                )
            }
        }
    }

    private static func bringAppToFront() {
        NSApp.unhide(nil)
        NSRunningApplication.current.activate(options: [.activateAllWindows, .activateIgnoringOtherApps])
        NSApp.activate(ignoringOtherApps: true)
        NSApp.arrangeInFront(nil)
        for window in NSApp.windows where window.contentViewController is ViewController {
            if window.isMiniaturized {
                window.deminiaturize(nil)
            }
            window.orderFrontRegardless()
            window.makeKeyAndOrderFront(nil)
        }
    }

    private static func activateApplicationFallback() {
        let bundleID = Bundle.main.bundleIdentifier ?? "com.mqldev.meetingsapp"
        let scriptSource = "tell application id \"\(bundleID)\" to activate"
        if let script = NSAppleScript(source: scriptSource) {
            var errorInfo: NSDictionary?
            script.executeAndReturnError(&errorInfo)
        }
    }

    private static func postTarget(_ target: WidgetQuickAction.Destination, delay: TimeInterval) {
        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
            switch target {
            case .joinMeetings:
                NotificationCenter.default.post(name: .widgetOpenJoinMeetingsPage, object: nil)
            case .schedule:
                NotificationCenter.default.post(name: .widgetOpenSchedulePage, object: nil)
            case .calendar:
                NotificationCenter.default.post(name: .widgetOpenCalendarPage, object: nil)
            case .settings:
                NotificationCenter.default.post(name: .widgetOpenSettingsPage, object: nil)
            case .signIn:
                NotificationCenter.default.post(name: .widgetSignInRequested, object: nil)
            case .openMeetWeb:
                NotificationCenter.default.post(name: .widgetOpenMeetWebRequested, object: nil)
            case .refreshMeetings:
                NotificationCenter.default.post(name: .widgetRefreshRequested, object: nil)
            }
        }
    }
}

extension Notification.Name {
    static let widgetOpenJoinMeetingsPage = Notification.Name("widgetOpenJoinMeetingsPage")
    static let widgetOpenSchedulePage = Notification.Name("widgetOpenSchedulePage")
    static let widgetOpenCalendarPage = Notification.Name("widgetOpenCalendarPage")
    static let widgetOpenSettingsPage = Notification.Name("widgetOpenSettingsPage")
    static let widgetSignInRequested = Notification.Name("widgetSignInRequested")
    static let widgetOpenMeetWebRequested = Notification.Name("widgetOpenMeetWebRequested")
    static let widgetRefreshRequested = Notification.Name("widgetRefreshRequested")
    static let widgetOpenMeetingLinkRequested = Notification.Name("widgetOpenMeetingLinkRequested")
    static let statusBarOpenSidebarPage = Notification.Name("statusBarOpenSidebarPage")
    static let statusBarPremiumAccessChanged = Notification.Name("statusBarPremiumAccessChanged")
    static let statusBarSignOutRequested = Notification.Name("statusBarSignOutRequested")
    static let meetingsSnapshotUpdated = Notification.Name("meetingsSnapshotUpdated")
}
