import AppKit

/// Borderless NSWindow subclass that can become key, allowing text field input.
class KeyableWindow: NSWindow {
    override var canBecomeKey: Bool { true }
    override var canBecomeMain: Bool { true }
}

extension AppDelegate {

    func setupWindows() {
        for screen in NSScreen.screens {
            let window = KeyableWindow(
                contentRect: screen.frame,
                styleMask: .borderless,
                backing: .buffered,
                defer: false
            )
            window.level = .screenSaver
            window.backgroundColor = .clear
            window.isOpaque = false
            window.hasShadow = false
            window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary]
            window.ignoresMouseEvents = true
            window.isReleasedWhenClosed = false

            let gradientView = EdgeGradientView(frame: NSRect(origin: .zero, size: screen.frame.size))
            gradientView.autoresizingMask = [.width, .height]
            window.contentView = gradientView

            window.alphaValue = 0.0
            window.orderFrontRegardless()
            overlayWindows.append(window)

            let pillW: CGFloat = 200
            let pillH: CGFloat = 80
            let pillX = screen.frame.origin.x + (screen.frame.width - pillW) / 2
            let pillY = screen.frame.origin.y + 40

            let pillWindow = NSWindow(
                contentRect: NSRect(x: pillX, y: pillY, width: pillW, height: pillH),
                styleMask: .borderless,
                backing: .buffered,
                defer: false
            )
            pillWindow.level = .screenSaver
            pillWindow.backgroundColor = .clear
            pillWindow.isOpaque = false
            pillWindow.hasShadow = false
            pillWindow.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary]
            pillWindow.ignoresMouseEvents = true
            pillWindow.isReleasedWhenClosed = false

            let pillView = NSView(frame: NSRect(x: 0, y: 0, width: pillW, height: pillH))
            pillView.wantsLayer = true
            pillView.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.6).cgColor
            pillView.layer?.cornerRadius = pillH / 2

            let label = NSTextField(labelWithString: "00:10")
            label.font = NSFont.monospacedSystemFont(ofSize: 36, weight: .bold)
            label.textColor = Settings.shared.gradientColor
            label.alignment = .center
            label.frame = NSRect(x: 0, y: 14, width: pillW, height: 50)
            pillView.addSubview(label)

            pillWindow.contentView = pillView
            pillWindow.alphaValue = 0.0
            pillWindow.orderFrontRegardless()

            countdownWindows.append(pillWindow)
            countdownLabels.append(label)
        }
    }

    func showCountdownPills() {
        for window in countdownWindows {
            if window.alphaValue < 1.0 {
                NSAnimationContext.runAnimationGroup { ctx in
                    ctx.duration = 0.2
                    window.animator().alphaValue = 1.0
                }
            }
        }
    }

    func hideCountdownPills() {
        for window in countdownWindows { window.alphaValue = 0.0 }
    }

    func updateCountdownLabels() {
        let seconds = max(remainingSeconds, 0)
        let text = String(format: "00:%02d", seconds)
        for label in countdownLabels { label.stringValue = text }
    }

    /// Single entry point for pulse schedule. Used by both work countdown and break.
    func applyPulseSchedule(remainingSeconds: Int, totalSeconds: Int) {
        if CountdownPulseSchedule.shouldBeSolid(remainingSeconds: remainingSeconds) {
            if !isSolid { makeSolid() }
        } else if CountdownPulseSchedule.shouldBlink(remainingSeconds: remainingSeconds) {
            triggerBlink(remainingSeconds: remainingSeconds, totalSeconds: totalSeconds)
        }
    }

    func triggerBlink(remainingSeconds: Int, totalSeconds: Int) {
        let settings = Settings.shared
        let scale = CGFloat(settings.intensityScale)
        let durationScale = settings.blinkDurationScale

        let countdownElapsed = Double(totalSeconds - remainingSeconds)
        let countdownTotal = Double(totalSeconds)
        let progress = min(max(countdownElapsed / countdownTotal, 0.0), 1.0)
        let baseIntensity = 0.15 + (0.60 * progress) // 0.15 at start, up to 0.75 at 0:00
        let intensity = min(baseIntensity * Double(scale), 1.0)

        let d = CountdownPulseSchedule.blinkDurations(remainingSeconds: remainingSeconds, durationScale: durationScale)
        let fadeIn = d.fadeIn
        let hold = d.hold
        let fadeOut = d.fadeOut

        let color = settings.gradientColor

        for window in overlayWindows {
            guard let view = window.contentView as? EdgeGradientView else { continue }
            view.intensity = CGFloat(intensity)
            view.color = color
            view.needsDisplay = true

            NSAnimationContext.runAnimationGroup { ctx in
                ctx.duration = fadeIn
                window.animator().alphaValue = 1.0
            } completionHandler: {
                DispatchQueue.main.asyncAfter(deadline: .now() + hold) {
                    NSAnimationContext.runAnimationGroup({ ctx in
                        ctx.duration = fadeOut
                        window.animator().alphaValue = 0.0
                    })
                }
            }
        }
    }

    func makeSolid() {
        isSolid = true
        let settings = Settings.shared
        let maxIntensity = min(0.75 * CGFloat(settings.intensityScale), 1.0)
        let color = settings.gradientColor

        for window in overlayWindows {
            guard let view = window.contentView as? EdgeGradientView else { continue }
            view.intensity = maxIntensity
            view.color = color
            view.needsDisplay = true
            NSAnimationContext.runAnimationGroup { ctx in
                ctx.duration = 0.3
                window.animator().alphaValue = 1.0
            }
        }
    }

    func resetOverlayToGradient() {
        for window in overlayWindows {
            window.ignoresMouseEvents = true
            let size = window.frame.size
            let gradientView = EdgeGradientView(frame: NSRect(origin: .zero, size: size))
            gradientView.autoresizingMask = [.width, .height]
            window.contentView = gradientView
            window.alphaValue = 0.0
        }
    }
}
