import AppKit

class AppDelegate: NSObject, NSApplicationDelegate {
    // Configuration
    var isDebugMode: Bool = false
    var workTimerDuration: Int {
        return isDebugMode ? 60 : 1500 // Debug: 1 min, Normal: 25 min
    }
    var countdownDuration: Int = 300 // 5 minutes of escalating flashes

    // Status bar
    var statusItem: NSStatusItem!
    var statusMenuItem: NSMenuItem!
    var debugMenuItem: NSMenuItem!
    var launchAtLoginMenuItem: NSMenuItem!
    var pauseMenuItem: NSMenuItem!
    var settingsMenuBuilder: SettingsMenuBuilder!

    // Overlay windows
    var overlayWindows: [NSWindow] = []
    var countdownWindows: [NSWindow] = []
    var countdownLabels: [NSTextField] = []

    // Timers
    var countdownTimer: Timer?
    var breakTimer: Timer?

    // State
    var remainingSeconds: Int = 0
    var isSolid = false
    var isPaused = false
    var currentSuggestion = ""
    var breakRemainingSeconds: Int = 300
    var breakCountdownLabels: [NSTextField] = []

    // Work log tracking
    var currentIntervalStartDate: Date?
    var currentIntent: String?
    var intervalCompleted: Bool = false
    var currentSuggestionFeedback: SuggestionFeedback?
    var currentWellnessReflection: WellnessReflection?

    // Text fields on ready screen (held for reading values)
    var reflectionField: NSTextField?
    var intentField: NSTextField?

    func applicationDidFinishLaunching(_ notification: Notification) {
        WorkLogStore.shared.clearOldEntries()
        if let saved = TimerPersistence.restore() {
            remainingSeconds = min(saved.remainingSeconds, workTimerDuration)
            isPaused = saved.isPaused
            currentIntervalStartDate = saved.intervalStartDate
        } else {
            remainingSeconds = workTimerDuration
            currentIntervalStartDate = Date()
        }
        setupStatusBar()
        setupWindows()
        startCountdown()
        updateStatusBar()
        NotificationManager.shared.requestPermission()
        NotificationManager.shared.postCycleStarted(durationMinutes: workTimerDuration / 60)

        // Check for updates silently on launch
        AutoUpdater.checkInBackground(silent: true)

        NotificationCenter.default.addObserver(
            self, selector: #selector(settingsDidChange),
            name: Settings.didChangeNotification, object: nil
        )
    }

    func applicationWillTerminate(_ notification: Notification) {
        TimerPersistence.save(remainingSeconds: remainingSeconds, isPaused: isPaused, intervalStartDate: currentIntervalStartDate)
    }

    @objc private func settingsDidChange() {
        let color = Settings.shared.gradientColor
        for label in countdownLabels {
            label.textColor = color
        }
        for window in overlayWindows {
            guard let view = window.contentView as? EdgeGradientView else { continue }
            view.color = color
            view.needsDisplay = true
        }
    }

    func startCountdown() {
        updateStatusBar()

        countdownTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
            guard let self = self else { timer.invalidate(); return }
            if self.isPaused { return }
            self.remainingSeconds -= 1
            self.updateStatusBar()

            if CountdownPulseSchedule.isInCountdownPhase(remainingSeconds: self.remainingSeconds, countdownDuration: self.countdownDuration, workTimerDuration: self.workTimerDuration) {
                let effective = min(self.countdownDuration, self.workTimerDuration)
                self.applyPulseSchedule(remainingSeconds: self.remainingSeconds, totalSeconds: effective)
                if self.remainingSeconds <= 10 {
                    self.showCountdownPills()
                    self.updateCountdownLabels()
                }
            }

            if self.remainingSeconds <= 0 {
                self.intervalCompleted = true
                self.showFullOverlay()
            }
        }
    }

    @objc func togglePause() {
        isPaused.toggle()
        updateStatusBar()
    }

    @objc func restartTimer() {
        countdownTimer?.invalidate()
        remainingSeconds = workTimerDuration
        currentIntervalStartDate = Date()
        intervalCompleted = false
        isPaused = false
        isSolid = false
        resetOverlayToGradient()
        hideCountdownPills()
        for window in countdownWindows { window.orderFrontRegardless() }
        startCountdown()
        updateStatusBar()
        NotificationManager.shared.postCycleStarted(durationMinutes: workTimerDuration / 60)
    }

    @objc func pauseFromOverlay() {
        saveCurrentInterval()
        isPaused = true
        breakTimer?.invalidate()
        breakCountdownLabels.removeAll()
        // Only reset to full duration if the interval actually completed;
        // otherwise preserve remaining time so the user can resume mid-countdown.
        if remainingSeconds <= 0 {
            remainingSeconds = workTimerDuration
            currentIntervalStartDate = Date()
            currentIntent = nil
            intervalCompleted = false
        }
        isSolid = false
        resetOverlayToGradient()
        hideCountdownPills()
        for window in countdownWindows { window.orderFrontRegardless() }
        startCountdown()
        updateStatusBar()
    }

    @objc func toggleDebugMode() {
        isDebugMode.toggle()
        debugMenuItem.state = isDebugMode ? .on : .off

        countdownTimer?.invalidate()
        breakTimer?.invalidate()
        breakCountdownLabels.removeAll()
        remainingSeconds = workTimerDuration
        isSolid = false
        isPaused = false

        currentIntervalStartDate = Date()
        currentIntent = nil
        intervalCompleted = false

        resetOverlayToGradient()
        hideCountdownPills()
        for window in countdownWindows { window.orderFrontRegardless() }

        startCountdown()
    }

    @objc func toggleLaunchAtLogin() {
        if LaunchAgent.isInstalled() {
            LaunchAgent.uninstall()
            launchAtLoginMenuItem.state = .off
        } else {
            LaunchAgent.install()
            launchAtLoginMenuItem.state = .on
        }
    }


    @objc func checkForUpdates() {
        AutoUpdater.checkInBackground(silent: false)
    }

    @objc func closePommedoro() {
        saveCurrentInterval()
        countdownTimer?.invalidate()
        breakTimer?.invalidate()
        for window in overlayWindows { window.orderOut(nil) }
        for window in countdownWindows { window.orderOut(nil) }
        NSApp.terminate(nil)
    }

    @objc func resumePommedoro() {
        saveCurrentInterval()

        isPaused = false
        isSolid = false
        breakTimer?.invalidate()
        breakCountdownLabels.removeAll()

        // Only reset to full duration if the interval completed;
        // otherwise preserve remaining time so the user resumes mid-countdown.
        if remainingSeconds <= 0 || intervalCompleted {
            remainingSeconds = workTimerDuration
            intervalCompleted = false
            currentIntervalStartDate = Date()
            // Carry forward the next intent
            let nextIntent = intentField?.stringValue.trimmingCharacters(in: .whitespacesAndNewlines)
            currentIntent = (nextIntent?.isEmpty == false) ? nextIntent : nil
        }
        reflectionField = nil
        intentField = nil

        resetOverlayToGradient()
        hideCountdownPills()
        for window in countdownWindows { window.orderFrontRegardless() }

        startCountdown()
        NotificationManager.shared.postCycleStarted(durationMinutes: workTimerDuration / 60)
    }

    @objc func dismissSuggestion() {
        currentSuggestionFeedback = .dismissed
        SuggestionManager.shared.dismiss(suggestion: currentSuggestion)
        resumePommedoro()
    }

    // MARK: - Work Log Helpers

    func saveCurrentInterval() {
        guard let startDate = currentIntervalStartDate else { return }
        let elapsed = Int(Date().timeIntervalSince(startDate))
        let reflection = reflectionField?.stringValue.trimmingCharacters(in: .whitespacesAndNewlines)

        let entry = WorkLogEntry(
            date: startDate,
            durationSeconds: elapsed,
            intent: currentIntent,
            completed: intervalCompleted,
            reflection: (reflection?.isEmpty == false) ? reflection : nil,
            additionalNotes: nil,
            suggestion: currentSuggestion.isEmpty ? nil : currentSuggestion,
            suggestionFeedback: currentSuggestionFeedback,
            wellnessReflection: currentWellnessReflection
        )
        WorkLogStore.shared.addEntry(entry)
        currentIntervalStartDate = nil
        currentSuggestionFeedback = nil
        currentWellnessReflection = nil
    }

    @objc func showWorkLog() {
        // Only save if meaningful work was done; skip trivial 0-second partials
        // so that viewing the log doesn't create throwaway entries.
        if let start = currentIntervalStartDate, Int(Date().timeIntervalSince(start)) >= 5 {
            saveCurrentInterval()
        }
        countdownTimer?.invalidate()
        breakTimer?.invalidate()
        breakCountdownLabels.removeAll()

        for (i, window) in overlayWindows.enumerated() {
            window.ignoresMouseEvents = false
            WorkLogViewBuilder.build(in: window, isPrimary: i == 0, delegate: self)
            NSAnimationContext.runAnimationGroup { ctx in
                ctx.duration = 0.3
                window.animator().alphaValue = 1.0
            }
        }
    }

    @objc func dismissWorkLogAndResume() {
        isPaused = false
        remainingSeconds = workTimerDuration
        isSolid = false
        intervalCompleted = false
        breakTimer?.invalidate()
        breakCountdownLabels.removeAll()

        // Preserve currentIntent so it carries into the next interval
        currentIntervalStartDate = Date()
        reflectionField = nil
        intentField = nil

        resetOverlayToGradient()
        hideCountdownPills()
        for window in countdownWindows { window.orderFrontRegardless() }

        startCountdown()
        NotificationManager.shared.postCycleStarted(durationMinutes: workTimerDuration / 60)
    }

    @objc func copyWorkLog() {
        let text = WorkLogStore.shared.todayLogAsText()
        NSPasteboard.general.clearContents()
        NSPasteboard.general.setString(text, forType: .string)
    }

    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        return false
    }
}
