import SwiftUI

struct VoiceWakeOverlayView: View {
    var controller: VoiceWakeOverlayController
    @FocusState private var textFocused: Bool
    @State private var isHovering: Bool = false
    @State private var closeHovering: Bool = false

    var body: some View {
        ZStack(alignment: .topLeading) {
            HStack(alignment: .top, spacing: 8) {
                if self.controller.model.isEditing {
                    TranscriptTextView(
                        text: Binding(
                            get: { self.controller.model.text },
                            set: { self.controller.updateText($0) }),
                        attributed: self.controller.model.attributed,
                        isFinal: self.controller.model.isFinal,
                        isOverflowing: self.controller.model.isOverflowing,
                        onBeginEditing: {
                            self.controller.userBeganEditing()
                        },
                        onEscape: {
                            self.controller.cancelEditingAndDismiss()
                        },
                        onEndEditing: {
                            self.controller.endEditing()
                        },
                        onSend: {
                            self.controller.requestSend()
                        })
                        .focused(self.$textFocused)
                        .frame(maxWidth: .infinity, minHeight: 32, maxHeight: .infinity, alignment: .topLeading)
                        .id("editing")
                } else {
                    VibrantLabelView(
                        attributed: self.controller.model.attributed,
                        onTap: {
                            self.controller.userBeganEditing()
                            self.textFocused = true
                        })
                        .frame(maxWidth: .infinity, minHeight: 32, maxHeight: .infinity, alignment: .topLeading)
                        .focusable(false)
                        .id("display")
                }

                Button {
                    self.controller.requestSend()
                } label: {
                    let sending = self.controller.model.isSending
                    let level = self.controller.model.level
                    ZStack {
                        GeometryReader { geo in
                            let width = geo.size.width
                            RoundedRectangle(cornerRadius: 8, style: .continuous)
                                .fill(Color.accentColor.opacity(0.12))
                            RoundedRectangle(cornerRadius: 8, style: .continuous)
                                .fill(Color.accentColor.opacity(0.25))
                                .frame(width: width * max(0, min(1, level)), alignment: .leading)
                                .animation(.easeOut(duration: 0.08), value: level)
                        }
                        .frame(height: 28)

                        ZStack {
                            Image(systemName: "paperplane.fill")
                                .opacity(sending ? 0 : 1)
                                .scaleEffect(sending ? 0.5 : 1)
                            Image(systemName: "checkmark.circle.fill")
                                .foregroundStyle(.green)
                                .opacity(sending ? 1 : 0)
                                .scaleEffect(sending ? 1.05 : 0.8)
                        }
                        .imageScale(.small)
                    }
                    .clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
                    .frame(width: 32, height: 28)
                    .animation(.spring(response: 0.35, dampingFraction: 0.78), value: sending)
                }
                .buttonStyle(.plain)
                .disabled(!self.controller.model.forwardEnabled || self.controller.model.isSending)
                .keyboardShortcut(.return, modifiers: [.command])
            }
            .padding(.vertical, 8)
            .padding(.horizontal, 10)
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
            .background {
                OverlayBackground()
                    .equatable()
            }
            .shadow(color: Color.black.opacity(0.22), radius: 14, x: 0, y: -2)
            .onHover { self.isHovering = $0 }

            // Close button rendered above and outside the clipped bubble
            CloseButtonOverlay(
                isVisible: self.controller.model.isEditing || self.isHovering || self.closeHovering,
                onHover: { self.closeHovering = $0 },
                onClose: { self.controller.cancelEditingAndDismiss() })
        }
        .padding(.top, self.controller.closeOverflow)
        .padding(.leading, self.controller.closeOverflow)
        .padding(.trailing, self.controller.closeOverflow)
        .padding(.bottom, self.controller.closeOverflow)
        .onAppear {
            self.updateFocusState(visible: self.controller.model.isVisible, editing: self.controller.model.isEditing)
        }
        .onChange(of: self.controller.model.isVisible) { _, visible in
            self.updateFocusState(visible: visible, editing: self.controller.model.isEditing)
        }
        .onChange(of: self.controller.model.isEditing) { _, editing in
            self.updateFocusState(visible: self.controller.model.isVisible, editing: editing)
        }
        .onChange(of: self.controller.model.attributed) { _, _ in
            self.controller.updateWindowFrame(animate: true)
        }
    }

    private func updateFocusState(visible: Bool, editing: Bool) {
        let shouldFocus = visible && editing
        guard self.textFocused != shouldFocus else { return }
        self.textFocused = shouldFocus
    }
}

private struct OverlayBackground: View {
    var body: some View {
        let shape = RoundedRectangle(cornerRadius: 12, style: .continuous)
        VisualEffectView(material: .hudWindow, blendingMode: .behindWindow)
            .clipShape(shape)
            .overlay(shape.strokeBorder(Color.white.opacity(0.16), lineWidth: 1))
    }
}

extension OverlayBackground: @MainActor Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool {
        true
    }
}

struct CloseHoverButton: View {
    var onClose: () -> Void

    var body: some View {
        Button(action: self.onClose) {
            Image(systemName: "xmark")
                .font(.system(size: 12, weight: .bold))
                .foregroundColor(Color.white.opacity(0.85))
                .frame(width: 22, height: 22)
                .background(Color.black.opacity(0.35))
                .clipShape(Circle())
                .shadow(color: Color.black.opacity(0.35), radius: 6, y: 2)
        }
        .buttonStyle(.plain)
        .focusable(false)
        .contentShape(Circle())
        .padding(6)
    }
}

struct CloseButtonOverlay: View {
    var isVisible: Bool
    var onHover: (Bool) -> Void
    var onClose: () -> Void

    var body: some View {
        Group {
            if self.isVisible {
                Button(action: self.onClose) {
                    Image(systemName: "xmark")
                        .font(.system(size: 12, weight: .bold))
                        .foregroundColor(Color.white.opacity(0.9))
                        .frame(width: 22, height: 22)
                        .background(Color.black.opacity(0.4))
                        .clipShape(Circle())
                        .shadow(color: Color.black.opacity(0.45), radius: 10, x: 0, y: 3)
                        .shadow(color: Color.black.opacity(0.2), radius: 2, x: 0, y: 0)
                }
                .buttonStyle(.plain)
                .focusable(false)
                .contentShape(Circle())
                .padding(6)
                .onHover { self.onHover($0) }
                .offset(x: -9, y: -9)
                .transition(.opacity)
            }
        }
        .allowsHitTesting(self.isVisible)
    }
}
