import SwiftUI

struct ChatBar: View {
    @Binding var text: String
    let suggestions: [String]
    let onPlusTap: () -> Void
    let onSlidersTap: () -> Void
    let onUploadTap: () -> Void
    let onRecordTap: () -> Void
    let onLibraryTap: () -> Void
    let onMicrophoneTap: () -> Void
    let onSendTap: () -> Void
    let onSuggestionTap: (String) -> Void
    let placeholder: String
    let scrollToBeginning: Bool
    @Binding var isChatBarFocused: Bool
    let audioFileName: String?
    let uploadProgress: Double
    let isUploading: Bool
    let uploadCompleted: Bool
    let onCloseAudio: () -> Void
    let onPlayPauseSelected: () -> Void
    let currentlyPlayingSongTitle: String?
    let currentArtworkGradient: LinearGradient?
    let isSelectedSongPlaying: Bool
    let onDeselectSong: () -> Void
    let hideTextInput: Bool
    let showCreateView: Bool
    let showSendButton: Bool

    // CreateView parameters
    @Binding var lyricsDescription: String
    @Binding var styleDescription: String
    let selectedModel: String
    let currentlyPlayingSong: Song?
    let currentlyPlayingSongId: String?
    let onSongPlayPause: ((String) -> Void)?
    let lyricsFocusMode: Bool
    let audioManager: AudioManager?
    let onModelVersionChange: ((String) -> Void)?

    // Advanced options bindings
    @Binding var weirdnessValue: Double
    @Binding var styleInfluenceValue: Double
    @Binding var audioInfluenceValue: Double
    @Binding var vocalGender: String

    @FocusState private var isTextFieldFocused: Bool
    @State private var forceMultilineLayout: Bool = false
    @State private var showActionMenu: Bool = false
    @State private var keyboardHeight: CGFloat = 0

    init(
        text: Binding<String>,
        suggestions: [String] = [],
        onPlusTap: @escaping () -> Void = {},
        onSlidersTap: @escaping () -> Void = {},
        onUploadTap: @escaping () -> Void = {},
        onRecordTap: @escaping () -> Void = {},
        onLibraryTap: @escaping () -> Void = {},
        onMicrophoneTap: @escaping () -> Void = {},
        onSendTap: @escaping () -> Void = {},
        onSuggestionTap: @escaping (String) -> Void = { _ in },
        placeholder: String = "What do you want to make?",
        scrollToBeginning: Bool = false,
        isChatBarFocused: Binding<Bool>,
        audioFileName: String? = nil,
        uploadProgress: Double = 0.0,
        isUploading: Bool = false,
        uploadCompleted: Bool = false,
        onCloseAudio: @escaping () -> Void = {},
        onPlayPauseSelected: @escaping () -> Void = {},
        currentlyPlayingSongTitle: String? = nil,
        currentArtworkGradient: LinearGradient? = nil,
        isSelectedSongPlaying: Bool = false,
        onDeselectSong: @escaping () -> Void = {},
        hideTextInput: Bool = false,
        showCreateView: Bool = false,
        showSendButton: Bool = false,
        lyricsDescription: Binding<String> = .constant(""),
        styleDescription: Binding<String> = .constant(""),
        selectedModel: String = "v4.5",
        currentlyPlayingSong: Song? = nil,
        currentlyPlayingSongId: String? = nil,
        onSongPlayPause: ((String) -> Void)? = nil,
        lyricsFocusMode: Bool = false,
        audioManager: AudioManager? = nil,
        onModelVersionChange: ((String) -> Void)? = nil,
        weirdnessValue: Binding<Double> = .constant(0.5),
        styleInfluenceValue: Binding<Double> = .constant(0.5),
        audioInfluenceValue: Binding<Double> = .constant(0.5),
        vocalGender: Binding<String> = .constant("Female")
    ) {
        self._text = text
        self.suggestions = suggestions
        self.onPlusTap = onPlusTap
        self.onSlidersTap = onSlidersTap
        self.onUploadTap = onUploadTap
        self.onRecordTap = onRecordTap
        self.onLibraryTap = onLibraryTap
        self.onMicrophoneTap = onMicrophoneTap
        self.onSendTap = onSendTap
        self.onSuggestionTap = onSuggestionTap
        self.placeholder = placeholder
        self.scrollToBeginning = scrollToBeginning
        self._isChatBarFocused = isChatBarFocused
        self.audioFileName = audioFileName
        self.uploadProgress = uploadProgress
        self.isUploading = isUploading
        self.uploadCompleted = uploadCompleted
        self.onCloseAudio = onCloseAudio
        self.onPlayPauseSelected = onPlayPauseSelected
        self.currentlyPlayingSongTitle = currentlyPlayingSongTitle
        self.currentArtworkGradient = currentArtworkGradient
        self.isSelectedSongPlaying = isSelectedSongPlaying
        self.onDeselectSong = onDeselectSong
        self.hideTextInput = hideTextInput
        self.showCreateView = showCreateView
        self.showSendButton = showSendButton
        self._lyricsDescription = lyricsDescription
        self._styleDescription = styleDescription
        self.selectedModel = selectedModel
        self.currentlyPlayingSong = currentlyPlayingSong
        self.currentlyPlayingSongId = currentlyPlayingSongId
        self.onSongPlayPause = onSongPlayPause
        self.lyricsFocusMode = lyricsFocusMode
        self.audioManager = audioManager
        self.onModelVersionChange = onModelVersionChange
        self._weirdnessValue = weirdnessValue
        self._styleInfluenceValue = styleInfluenceValue
        self._audioInfluenceValue = audioInfluenceValue
        self._vocalGender = vocalGender
    }
    
    var body: some View {
        VStack(spacing: 0) {

            // Referenced song (if available)
            if let songTitle = currentlyPlayingSongTitle, let gradient = currentArtworkGradient, !showCreateView {
                ReferencedSong(
                    songTitle: songTitle,
                    artworkGradient: gradient,
                    isPlaying: isSelectedSongPlaying,
                    onPlayPause: onPlayPauseSelected,
                    onClose: onDeselectSong
                )
            }

            if !suggestions.isEmpty && !showCreateView {
                suggestionsView
            }

            // Audio file display (when present)
            if let audioFileName = audioFileName {
                audioFileView
            }


            // Text input and buttons (hide text input if hideTextInput is true)
            if !hideTextInput {
                textInputField
            }

            buttonsRow

            // CreateView content (shown when in .full mode)

            if showCreateView {
                createViewContent
            }
        }
        .contentShape(Rectangle())
        .onTapGesture {
            // Dismiss keyboard when tapping outside text fields (only in create view mode)
            if showCreateView {
                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
            }
        }
    }
    

    private var textInputField: some View {
        TextField(placeholder, text: $text, axis: .vertical)
            .font(Constants.Typography.mediumTitle)
            .foregroundColor(.white)
            .tracking(0.32)
            .textFieldStyle(PlainTextFieldStyle())
            .focused($isTextFieldFocused)
            .lineLimit(1...8)
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
            .onChange(of: text) { oldValue, newValue in
                // Only auto-focus when user is actively typing (text increased)
                if !newValue.isEmpty && newValue.count > oldValue.count {
                    isTextFieldFocused = true
                }

                // Force multiline if user added a newline
                if newValue.contains("\n") && !forceMultilineLayout {
                    forceMultilineLayout = true
                }

                // Reset force multiline if text is empty or becomes short again
                if newValue.isEmpty || (newValue.count <= 32 && !newValue.contains("\n")) {
                    forceMultilineLayout = false
                }
            }
            .onChange(of: isTextFieldFocused) { isFocused in
                isChatBarFocused = isFocused
            }
    }

    private var buttonsRow: some View {
        ZStack {
            // Background layer with buttons
            HStack(spacing: 0) {
                // Plus button and sliders on left
                if audioFileName == nil {
                    HStack(spacing: 8) {
                        integratedPlusButton

                        // Sliders button (only in flex mode, not full mode)
                        if !showCreateView {
                            MediumButton.secondaryIcon("Icon/sliders") {
                                onSlidersTap()
                            }
                        }
                    }
                }

                Spacer()

                // Mic or Send button on right
                rightButton
            }

            // Centered title overlay (only in .full mode)
            if showCreateView {
                VStack(spacing: 0) {
                    Text("Custom")
                        .font(Constants.Typography.mediumTitle)
                        .foregroundColor(Constants.Colors.Foreground.primary)
                        .tracking(0.24)

                    CreditsDisplay(selectedModel: selectedModel)
                }
            }
        }
        .padding(.horizontal, 16)
        .padding(.bottom, 16)
    }

    private var integratedInputBar: some View {
        let shouldUseMultilineLayout = text.count > 32 || forceMultilineLayout
        let cornerRadius: CGFloat = shouldUseMultilineLayout ? 24 : 100
        let minHeight: CGFloat = 56

        return HStack(alignment: shouldUseMultilineLayout ? .bottom : .center, spacing: 16) {

            // Always show plus button when no audio file present
            if audioFileName == nil {
                HStack(spacing: 8) {
                    integratedPlusButton

                    // Sliders button (only in flex mode, not full mode)
                    if !showCreateView {
                        MediumButton.secondaryIcon("Icon/sliders") {
                            onSlidersTap()
                        }
                    }
                }
            }

            if audioFileName != nil {
                Spacer()
                    .frame(width: 0.1)
            }

            // Text Input
            adaptiveTextInput

            rightButton
        }
        .padding(.horizontal, shouldUseMultilineLayout ? 8 : 8)
        .padding(.vertical, shouldUseMultilineLayout ? 8 : 8)
        .frame(minHeight: minHeight)
        .background(
            RoundedRectangle(cornerRadius: cornerRadius)
                .stroke(Constants.Colors.Border.primary, lineWidth: 1)
        )
        .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
        .animation(.easeInOut(duration: 0.2), value: shouldUseMultilineLayout)
    }
    
    private var adaptiveTextInput: some View {
        let shouldUseMultilineLayout = text.count > 32 || forceMultilineLayout
        let alignment: Alignment = shouldUseMultilineLayout ? .topLeading : .leading
        
        return ZStack(alignment: alignment) {
            if text.isEmpty {
                Text(placeholder)
                    .font(Constants.Typography.mediumTitle)
                    .foregroundColor(Constants.Colors.Foreground.primary.opacity(0.3))
                    .tracking(0.32)
                    .padding(.top, shouldUseMultilineLayout ? 4 : 0)
            }
            
            TextField("", text: $text, axis: .vertical)
                .font(Constants.Typography.mediumTitle)
                .foregroundColor(.white)
                .tracking(0.32)
                .textFieldStyle(PlainTextFieldStyle())
                .focused($isTextFieldFocused)
                .lineLimit(shouldUseMultilineLayout ? 1...4 : 1...1)
                .onChange(of: text) { oldValue, newValue in
                    // Only auto-focus when user is actively typing (text increased)
                    // Don't auto-focus when text is programmatically set (like from suggestions)
                    if !newValue.isEmpty && newValue.count > oldValue.count {
                        isTextFieldFocused = true
                    }

                    // Reset force multiline if text is empty or becomes short again
                    if newValue.isEmpty || (newValue.count <= 32 && !newValue.contains("\n")) {
                        forceMultilineLayout = false
                    }

                    // Force multiline if user added a newline
                    if newValue.contains("\n") && !forceMultilineLayout {
                        forceMultilineLayout = true
                    }
                }
                .onChange(of: isTextFieldFocused) { isFocused in
                    isChatBarFocused = isFocused
                }
        }
        .frame(minHeight: 24)
    }
    
    private var audioFileView: some View {
        HStack(spacing: 24) {
            
            HStack(spacing: 4){
                Image("Icon/audio-file")
                    .resizable()
                    .renderingMode(.template)
                    .frame(width: 16, height: 16)
                    .foregroundColor(Constants.Colors.Foreground.primary)
                
                Text(audioFileName?.uppercased() ?? "")
                    .font(Constants.Typography.timecode.weight(.medium))
                    .foregroundColor(Constants.Colors.Foreground.primary)
                    .tracking(0.24)
            }
            
            // Progress bar
            if isUploading || uploadCompleted {
                GeometryReader { geometry in
                    ZStack(alignment: .leading) {
                        // Background track
                        RoundedRectangle(cornerRadius: 100)
                            .fill(Color.white.opacity(0.04))
                            .frame(height: 4)
                        
                        // Progress track
                        RoundedRectangle(cornerRadius: 100)
                            .fill(uploadCompleted ? Color.green : Constants.Colors.Accent.brand)
                            .frame(width: geometry.size.width * CGFloat(uploadProgress), height: 4)
                            .animation(.easeInOut(duration: 0.3), value: uploadProgress)
                            .animation(.easeInOut(duration: 0.3), value: uploadCompleted)
                    }
                }
                .frame(height: 4)
                .opacity(uploadCompleted && uploadProgress >= 1.0 ? 0 : 1)
                .animation(.easeOut(duration: 1.0).delay(0.5), value: uploadCompleted)
            } else {
                Spacer()
            }
            
            Button {
                onCloseAudio()
            } label: {
                Image("Icon/close")
                    .resizable()
                    .renderingMode(.template)
                    .frame(width: 16, height: 16)
                    .foregroundColor(Constants.Colors.Foreground.tertiary)
            }
            .buttonStyle(PlainButtonStyle())
        }
        .padding(.vertical, 16)
        .padding(.horizontal, 16)
    }
    
    private var integratedPlusButton: some View {
        Button {
            showActionMenu = true
        } label: {
            ZStack {
                Circle()
                    .fill(Constants.Colors.Background.Fog.thin)
                    .frame(width: 40, height: 40)

                Image("Icon/plus")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 16, height: 16)
                    .foregroundColor(Constants.Colors.Foreground.primary)
            }
        }
        .buttonStyle(PlainButtonStyle())
        .sheet(isPresented: $showActionMenu) {
            ActionMenuSheet(
                currentModel: selectedModel,
                onModelSelect: { model in
                    onModelVersionChange?(model)
                },
                onUploadTap: onUploadTap,
                onRecordTap: onRecordTap,
                onLibraryTap: onLibraryTap,
                onPersonaTap: {
                    // TODO: Handle persona selection
                    print("Persona tapped")
                }
            )
        }
    }
    
    @ViewBuilder
    private var rightButton: some View {
        if showSendButton || !text.isEmpty {
            // Send Button using Aura Medium Icon Button
            // Dim to 30% opacity when in full mode and both lyrics and style are empty
            let shouldDim = showSendButton && lyricsDescription.isEmpty && styleDescription.isEmpty

            if showCreateView {
                // Show text button with label when in full mode
                MediumButton.aura("Create", leftIconAssetName: "Icon/music") {
                    onSendTap()
                }
                .opacity(shouldDim ? 0.3 : 1.0)
            } else {
                // Show icon-only button when not in full mode
                MediumButton.auraIcon("Icon/arrow-up") {
                    onSendTap()
                }
                .opacity(shouldDim ? 0.3 : 1.0)
            }
        } else {
            // Microphone Icon
            Button {
                onMicrophoneTap()
            } label: {
                Image("Icon/microphone")
                    .resizable()
                    .renderingMode(.template)
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 24, height: 24)
                    .foregroundColor(Constants.Colors.Background.Fog.dense)
                    .padding(.trailing, 8)
            }
            .buttonStyle(PlainButtonStyle())
        }
    }
    
    private var suggestionsView: some View {
        ScrollViewReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 8) {
                    // Suggestion pills
                    ForEach(Array(suggestions.prefix(5).enumerated()), id: \.offset) { index, suggestion in
                        Button(action: {
                            onSuggestionTap(suggestion)
                        }) {
                            Text(suggestion.uppercased())
                                .font(Constants.Typography.timecode)
                                .kerning(0.2)
                                .foregroundColor(Constants.Colors.Foreground.primary)
                                .lineLimit(1)
                                .padding(.horizontal, 10)
                                .padding(.vertical, 8)
                                .background(
                                    RoundedRectangle(cornerRadius: 100)
                                        .fill(Constants.Colors.Background.Fog.thin)
                                )
                        }
                        .buttonStyle(PlainButtonStyle())
                        .id(index == 0 ? "first" : "suggestion_\(index)")
                    }
                }
                .padding(.horizontal, 16)
                .padding(.bottom, 12)
            }
            .onChange(of: scrollToBeginning) { shouldScroll in
                if shouldScroll {
                    withAnimation(.easeInOut(duration: 0.3)) {
                        proxy.scrollTo("first", anchor: .leading)
                    }
                }
            }
        }
    }
    
    private func colorForSuggestion(_ suggestion: String, index: Int) -> Color {
        // Check if this is an additive suggestion (starts with +)
        if suggestion.hasPrefix("+") {
            // Additive suggestions use foreground.inactive
            return Constants.Colors.Foreground.inactive
        } else {
            // Regular suggestions use foreground.primary
            return Constants.Colors.Foreground.primary
        }
    }

    private var createViewContent: some View {
        ScrollViewWithSheetSupport {
            VStack(spacing: 16) {
                // Audio Player (when there's a selected song)
                if let selectedSong = currentlyPlayingSong {
                    CreateAudioPlayer(
                        songTitle: selectedSong.title,
                        artworkGradient: createGradientForSong(selectedSong),
                        isPlaying: currentlyPlayingSongId == selectedSong.id,
                        onPlayPause: {
                            onSongPlayPause?(selectedSong.id)
                        },
                        audioManager: audioManager
                    )
                }

                // Lyrics Description Component
                LyricsDescription(
                    lyricsText: $lyricsDescription,
                    startExpanded: true,
                    placeholderText: "Write lyrics or leave empty for instrumental",
                    onSaveLyrics: { currentLyricsText in
                        print("Save lyrics: \(currentLyricsText)")
                    },
                    showOnlyUndo: false,
                    hideFooterControls: false,
                    customHeight: lyricsFocusMode ? 340 : nil
                )

                // Style Description Component
                StyleDescription(
                    styleText: $styleDescription,
                    modelVersion: selectedModel,
                    startExpanded: !lyricsFocusMode
                ) { currentStyleText in
                    print("Save style: \(currentStyleText)")
                }

                // Advanced Options Component
                AdvancedOptions(
                    weirdnessValue: $weirdnessValue,
                    styleInfluenceValue: $styleInfluenceValue,
                    audioInfluenceValue: $audioInfluenceValue,
                    vocalGender: $vocalGender
                )
            }
            .padding(.horizontal, 16)
            .padding(.top, 0)
            .padding(.bottom, 16 + keyboardHeight)

        }
        .onAppear {
            // Setup keyboard notifications
            NotificationCenter.default.addObserver(
                forName: UIResponder.keyboardWillShowNotification,
                object: nil,
                queue: .main
            ) { notification in
                if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
                    withAnimation(.easeOut(duration: 0.3)) {
                        keyboardHeight = keyboardFrame.height
                    }
                }
            }

            NotificationCenter.default.addObserver(
                forName: UIResponder.keyboardWillHideNotification,
                object: nil,
                queue: .main
            ) { _ in
                withAnimation(.easeOut(duration: 0.3)) {
                    keyboardHeight = 0
                }
            }
        }
    }

    private func createGradientForSong(_ song: Song) -> LinearGradient {
        guard let artwork = song.artwork else {
            // Default gradient
            return LinearGradient(
                colors: [
                    Color(red: 0.8, green: 0.4, blue: 0.9),
                    Color(red: 0.4, green: 0.6, blue: 1.0)
                ],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            )
        }

        // Create consistent gradient based on artwork string hash
        let hash = artwork.hashValue
        let seed1 = abs(hash % 1000)
        let seed2 = abs((hash / 1000) % 1000)

        return LinearGradient(
            colors: [
                Color(
                    red: 0.3 + (Double(seed1 % 600) / 1000.0),
                    green: 0.3 + (Double((seed1 + 200) % 600) / 1000.0),
                    blue: 0.3 + (Double((seed1 + 400) % 600) / 1000.0)
                ),
                Color(
                    red: 0.3 + (Double(seed2 % 600) / 1000.0),
                    green: 0.3 + (Double((seed2 + 200) % 600) / 1000.0),
                    blue: 0.3 + (Double((seed2 + 400) % 600) / 1000.0)
                )
            ],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
    }

}

#Preview {
    VStack(spacing: 20) {
        // Empty State
        ChatBar(
            text: .constant(""),
            onPlusTap: { print("Plus tapped") },
            onMicrophoneTap: { print("Microphone tapped") },
            onSendTap: { print("Send tapped") },
            onSuggestionTap: { suggestion in print("Suggestion tapped: \(suggestion)") },
            isChatBarFocused: .constant(false)
        )
        
        // With Regular Suggestions State
        ChatBar(
            text: .constant(""),
            suggestions: ["EXTEND", "EDIT LYRICS", "REPLACE SECTION", "CHANGE GENRE", "MAKE SLOWER"],
            onPlusTap: { print("Plus tapped") },
            onMicrophoneTap: { print("Microphone tapped") },
            onSendTap: { print("Send tapped") },
            onSuggestionTap: { suggestion in print("Suggestion tapped: \(suggestion)") },
            isChatBarFocused: .constant(false),
            onPlayPauseSelected: { print("Play/Pause selected song") },
            currentlyPlayingSongTitle: "Song Title (#1)",
            currentArtworkGradient: LinearGradient(
                colors: [Color.blue, Color.purple],
                startPoint: .topLeading,
                endPoint: .bottomTrailing
            ),
            isSelectedSongPlaying: true
        )
        
        // With Genre Suggestions State (+ prefix)
        ChatBar(
            text: .constant(""),
            suggestions: ["+POP", "+ROCK", "+HIP-HOP", "+SYNTHWAVE", "+LO-FI"],
            onPlusTap: { print("Plus tapped") },
            onMicrophoneTap: { print("Microphone tapped") },
            onSendTap: { print("Send tapped") },
            onSuggestionTap: { suggestion in print("Suggestion tapped: \(suggestion)") },
            isChatBarFocused: .constant(false)
        )
        
        // Filled State
        ChatBar(
            text: .constant("Hello world"),
            onPlusTap: { print("Plus tapped") },
            onMicrophoneTap: { print("Microphone tapped") },
            onSendTap: { print("Send tapped") },
            onSuggestionTap: { suggestion in print("Suggestion tapped: \(suggestion)") },
            isChatBarFocused: .constant(false)
        )
        
        Spacer()
    }
    .background(Constants.Colors.Background.primary)
}

// Preference key to track view height
struct ViewHeightKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}
