import SwiftUI

struct MiniRecorderView<S: RecorderStateProvider & ObservableObject>: View {
    @ObservedObject var stateProvider: S
    @ObservedObject var recorder: Recorder
    @EnvironmentObject var windowManager: MiniWindowManager
    @EnvironmentObject private var enhancementService: AIEnhancementService
    @AppStorage("showLiveTextPreview") private var showLiveTextPreview = false

    @State private var activePopover: ActivePopoverState = .none

    // MARK: - Layout Constants

    private let controlBarHeight: CGFloat = 40
    private let compactWidth: CGFloat = 184
    private let expandedWidth: CGFloat = 300
    private let compactCornerRadius: CGFloat = 20
    private let expandedCornerRadius: CGFloat = 14

    // true when live transcript is streaming in during recording
    private var hasLiveTranscript: Bool {
        showLiveTextPreview
            && stateProvider.recordingState == .recording
            && !stateProvider.partialTranscript.isEmpty
    }

    private var controlBar: some View {
        HStack(spacing: 0) {
            RecorderPromptButton(
                activePopover: $activePopover,
                buttonSize: 22,
                padding: EdgeInsets()
            )
            .padding(.leading, 12)

            Spacer(minLength: 0)

            RecorderStatusDisplay(
                currentState: stateProvider.recordingState,
                audioMeter: recorder.audioMeter
            )

            Spacer(minLength: 0)

            RecorderPowerModeButton(
                activePopover: $activePopover,
                buttonSize: 22,
                padding: EdgeInsets()
            )
            .padding(.trailing, 12)
        }
        .frame(height: controlBarHeight)
    }

    private var transcriptSection: some View {
        VStack(spacing: 0) {
            if hasLiveTranscript {
                LiveTranscriptView(text: stateProvider.partialTranscript)
                Divider().background(Color.proatBorder.opacity(0.4))
            }
        }
    }

    // true when the recorder is actively capturing audio — drives the breathing teal accent
    private var isRecordingActive: Bool {
        stateProvider.recordingState == .recording
    }

    var body: some View {
        if windowManager.isVisible {
            let cornerRadius: CGFloat = hasLiveTranscript ? expandedCornerRadius : compactCornerRadius
            let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)

            VStack(spacing: 0) {
                transcriptSection
                controlBar
            }
            .frame(width: hasLiveTranscript ? expandedWidth : compactWidth)
            .background(
                ZStack {
                    // Refined glass pill base — neutral when idle.
                    ProatGlassBackground()
                    Color.proatBgRaised.opacity(0.32)

                    // Breathing teal accent only while recording.
                    if isRecordingActive {
                        BreathingTealAccent(shape: shape)
                    }
                }
            )
            .clipShape(shape)
            .overlay(
                shape.stroke(
                    isRecordingActive ? Color.proatTeal.opacity(0.55) : Color.proatBorder.opacity(0.6),
                    lineWidth: 1
                )
            )
            .proatShadowFloat()
            .animation(.easeInOut(duration: 0.3), value: hasLiveTranscript)
            .animation(.easeInOut(duration: 0.3), value: isRecordingActive)
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
        }
    }
}

/// Soft breathing teal wash shown only while the mini-recorder is recording.
private struct BreathingTealAccent: View {
    let shape: RoundedRectangle
    @State private var breathe = false

    var body: some View {
        LinearGradient.proatTeal
            .opacity(breathe ? 0.42 : 0.20)
            .clipShape(shape)
            .onAppear {
                withAnimation(.easeInOut(duration: 1.6).repeatForever(autoreverses: true)) {
                    breathe = true
                }
            }
    }
}
