import AppKit

@MainActor
final class StatusBarController: NSObject {
    private let authService = GoogleOAuthService.shared
    private let statusItem: NSStatusItem
    private var observers: [NSObjectProtocol] = []
    private var hasPremiumAccess = false

    override init() {
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        super.init()

        if let icon = NSImage(systemSymbolName: "calendar.badge.clock", accessibilityDescription: "Meetings") {
            icon.isTemplate = true
            statusItem.button?.image = icon
        } else {
            statusItem.button?.title = "Meetings"
        }
        statusItem.button?.setAccessibilityLabel("Meetings status menu")
        rebuildMenu()

        let center = NotificationCenter.default
        observers.append(center.addObserver(forName: .meetingsSnapshotUpdated, object: nil, queue: .main) { [weak self] _ in
            self?.rebuildMenu()
        })
        observers.append(center.addObserver(forName: .statusBarSignOutRequested, object: nil, queue: .main) { [weak self] _ in
            self?.rebuildMenu()
        })
        observers.append(center.addObserver(forName: .widgetSignInRequested, object: nil, queue: .main) { [weak self] _ in
            self?.rebuildMenu()
        })
        observers.append(center.addObserver(forName: .statusBarPremiumAccessChanged, object: nil, queue: .main) { [weak self] notification in
            guard let self else { return }
            if let hasPremium = notification.userInfo?["hasPremiumAccess"] as? Bool {
                self.hasPremiumAccess = hasPremium
            }
            self.rebuildMenu()
        })
    }

    deinit {
        observers.forEach { NotificationCenter.default.removeObserver($0) }
    }

    private func rebuildMenu() {
        let menu = NSMenu()

        let openAppItem = NSMenuItem(title: "Open App", action: #selector(openAppClicked), keyEquivalent: "")
        openAppItem.target = self
        menu.addItem(openAppItem)

        menu.addItem(.separator())
        addOpenSidebarItem(title: "Join Meetings", pageRaw: 0, to: menu)
        addOpenSidebarItem(title: "Schedule", pageRaw: 1, to: menu)
        addOpenSidebarItem(title: "Calendar", pageRaw: 2, to: menu)
        addOpenSidebarItem(title: "Widgets", pageRaw: 3, to: menu)
        addOpenSidebarItem(title: "Settings", pageRaw: 4, to: menu)

        let signedIn = authService.loadTokens() != nil
        if signedIn && hasPremiumAccess {
            let topMeetings = WidgetMeetingStore.load().prefix(3).map { $0 }
            menu.addItem(.separator())
            let header = NSMenuItem(title: "Top meetings", action: nil, keyEquivalent: "")
            header.isEnabled = false
            menu.addItem(header)

            if topMeetings.isEmpty {
                let empty = NSMenuItem(title: "No upcoming meetings", action: nil, keyEquivalent: "")
                empty.isEnabled = false
                menu.addItem(empty)
            } else {
                for meeting in topMeetings {
                    let titleText = truncatedMeetingTitle(meeting.title)
                    let title = "\(meeting.timeText)  \(titleText)"
                    let item = NSMenuItem(title: title, action: #selector(meetingClicked(_:)), keyEquivalent: "")
                    item.target = self
                    item.representedObject = meeting.joinLink
                    menu.addItem(item)
                }
            }
        }

        if signedIn {
            menu.addItem(.separator())
            let signOutItem = NSMenuItem(title: "Sign Out", action: #selector(signOutClicked), keyEquivalent: "")
            signOutItem.target = self
            menu.addItem(signOutItem)
        } else {
            menu.addItem(.separator())
            let signInItem = NSMenuItem(title: "Sign In", action: #selector(signInClicked), keyEquivalent: "")
            signInItem.target = self
            menu.addItem(signInItem)
        }

        menu.addItem(.separator())
        let quitItem = NSMenuItem(title: "Quit", action: #selector(quitClicked), keyEquivalent: "q")
        quitItem.target = self
        menu.addItem(quitItem)

        statusItem.menu = menu
    }

    @objc private func openAppClicked() {
        bringAppToFront()
    }

    @objc private func signInClicked() {
        bringAppToFront()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
            NotificationCenter.default.post(name: .widgetSignInRequested, object: nil)
        }
    }

    @objc private func signOutClicked() {
        bringAppToFront()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
            NotificationCenter.default.post(name: .statusBarSignOutRequested, object: nil)
        }
    }

    @objc private func openSidebarPageClicked(_ sender: NSMenuItem) {
        guard let pageRaw = sender.representedObject as? Int else { return }
        bringAppToFront()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
            NotificationCenter.default.post(name: .statusBarOpenSidebarPage, object: nil, userInfo: ["page": pageRaw])
        }
    }

    @objc private func meetingClicked(_ sender: NSMenuItem) {
        guard let link = sender.representedObject as? String,
              let url = URL(string: link.trimmingCharacters(in: .whitespacesAndNewlines)) else { return }
        let routed = authService.urlForPreferredGoogleAccountIfPossible(url)
        NSWorkspace.shared.open(routed)
    }

    @objc private func quitClicked() {
        NSApp.terminate(nil)
    }

    private 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 func truncatedMeetingTitle(_ title: String) -> String {
        let trimmed = title.trimmingCharacters(in: .whitespacesAndNewlines)
        guard trimmed.count > 10 else { return trimmed }
        return "\(trimmed.prefix(10))..."
    }

    private func addOpenSidebarItem(title: String, pageRaw: Int, to menu: NSMenu) {
        let item = NSMenuItem(title: title, action: #selector(openSidebarPageClicked(_:)), keyEquivalent: "")
        item.target = self
        item.representedObject = pageRaw
        menu.addItem(item)
    }
}

