import SwiftUI
import ComponentLibrary
import IdentifiedCollections

// Import AudioManager for progress observation
@preconcurrency import Foundation

struct ChatsView: View {
    let messages: IdentifiedArrayOf<ChatMessage>
    let currentlyPlayingSongId: String?
    let currentlySelectedSongId: String?
    let isLoading: Bool
    let onSongPlayPause: (String) -> Void
    let onSongSelect: (String) -> Void
    let onCreateMore: () -> Void
    let onLyricsExpand: () -> Void
    let onLinkTap: ((String) -> Void)?
    let shouldAutoScroll: Bool
    
    @State private var isNearBottom: Bool = true
    
    var body: some View {
        ScrollViewReader { proxy in
            ScrollView(showsIndicators: false) {
                LazyVStack(spacing: 24) {
                    ForEach(messages) { message in
                        if message.isOutgoing {
                            OutgoingMessage(message: message.content, audioFileName: message.audioFileName)
                        } else {
                            // Check if this is a song generation message
                            if let songData = message.songData {
                                SimpleSongGenerationView(
                                    message: message.content,
                                    songs: songData.songs,
                                    songData: songData, // Pass full songData to access lyrics
                                    currentlyPlayingSongId: currentlyPlayingSongId,
                                    currentlySelectedSongId: currentlySelectedSongId,
                                    currentLyrics: nil, // TODO: Pass currentLyrics from state if needed
                                    isLastSongGeneration: isLastSongGenerationMessage(message),
                                    onPlayPause: { songId in
                                        onSongPlayPause(songId)
                                    },
                                    onSongSelect: { songId in
                                        onSongSelect(songId)
                                    },
                                    onLyricsExpand: onLyricsExpand,
                                    onCreateMore: {
                                        onCreateMore()
                                    }
                                )
                            } else {
                                IncomingMessage(message: message.content, onLinkTap: onLinkTap)
                            }
                        }
                    }
                    
                    // Show loading message when waiting for response
                    if isLoading {
                        IncomingMessageLoading()
                    }
                    
                    
                    // Invisible element at the very bottom for scrolling
                    Color.clear
                        .frame(height: 180)
                        .id("messagesBottom")
                }
                .padding(.horizontal, 16)
                .padding(.top, 16)
                .onChange(of: messages.count) { _, _ in
                    // Auto-scroll to bottom when new message is added
                    withAnimation(.easeOut(duration: 0.3)) {
                        proxy.scrollTo("messagesBottom", anchor: .bottom)
                    }
                }
                .onChange(of: shouldAutoScroll) { _, shouldScroll in
                    if shouldScroll && isNearBottom {
                        // Auto-scroll to bottom when keyboard appears and user is near end
                        withAnimation(.easeOut(duration: 0.3)) {
                            proxy.scrollTo("messagesBottom", anchor: .bottom)
                        }
                    }
                }
                .background(
                    GeometryReader { geometry in
                        Color.clear
                            .onAppear {
                                // Initial scroll position check
                                updateScrollPosition(geometry: geometry)
                            }
                            .onChange(of: geometry.frame(in: .global)) { _, _ in
                                updateScrollPosition(geometry: geometry)
                            }
                    }
                )
            }
        }
    }
    
    private func isLastSongGenerationMessage(_ message: ChatMessage) -> Bool {
        // Find the last message with song data
        let lastSongMessage = messages.last { $0.songData != nil }
        return message.id == lastSongMessage?.id
    }
    
    private func updateScrollPosition(geometry: GeometryProxy) {
        // Check if the scroll view is near the bottom
        let frame = geometry.frame(in: .global)
        let threshold: CGFloat = 100 // Consider "near bottom" if within 100 points
        
        // In a ScrollView, when we're at the bottom, the frame's maxY should be close to the screen height
        let screenHeight = UIScreen.main.bounds.height
        let distanceFromBottom = screenHeight - frame.maxY
        
        let wasNearBottom = isNearBottom
        isNearBottom = distanceFromBottom <= threshold
        
        // Debug logging
        if wasNearBottom != isNearBottom {
            print("📍 Scroll position changed - Near bottom: \(isNearBottom)")
        }
    }
    
    private func isCreateMoreMessage(_ content: String) -> Bool {
        let lowercased = content.lowercased()
        return lowercased.contains("create another version") ||
               lowercased.contains("create more") ||
               lowercased.contains("make another") ||
               lowercased.contains("generate another")
    }
}

struct SimpleSongGenerationView: View {
    let message: String
    let songs: [Song]
    let songData: SongResponse? // Add songData to access lyrics
    let currentlyPlayingSongId: String?
    let currentlySelectedSongId: String?
    let currentLyrics: String? // Add currentLyrics parameter
    let isLastSongGeneration: Bool
    let onPlayPause: (String) -> Void
    let onSongSelect: (String) -> Void
    let onLyricsExpand: () -> Void
    let onCreateMore: () -> Void
    
    @State private var lyricsExpanded: Bool = false
    @State private var showMessage: Bool = true
    @State private var showLyrics: Bool = false
    @State private var showSongs: Bool = false
    @State private var typedMessage: String = ""
    @State private var hasAnimated: Bool = false
    
    var body: some View {
        VStack(alignment: .leading, spacing: message.isEmpty ? 0 : 16) {
            // Text Response with typing animation (only show if message has content)
            if !message.isEmpty && showMessage {
                IncomingMessage(message: typedMessage, shouldAnimate: false)
            }

            // TODO: JY - Disabled / WIP
            // Lyrics Section with fade in
            // Check both songData.lyrics and currentLyrics (lyrics might be in state)
//            if let lyrics = songData?.lyrics ?? currentLyrics, showLyrics {
//                InlineLyricsView(
//                    lyrics: lyrics,
//                    isExpanded: lyricsExpanded,
//                    onSeeMoreTap: {
//                        withAnimation(.easeInOut(duration: 0.3)) {
//                            lyricsExpanded.toggle()
//                        }
//                    }
//                )
//                .opacity(showLyrics ? 1.0 : 0.0)
//                .animation(.easeInOut(duration: 0.5), value: showLyrics)
//            }
            
            // Songs Section with simple fade-in animation
            if !songs.isEmpty && showSongs {
                VStack(spacing: 16) {
                    HStack(spacing: 16) {
                        ForEach(songs) { song in
                            SimpleSongCard(
                                song: song,
                                isPlaying: currentlyPlayingSongId == song.id,
                                isSelected: currentlySelectedSongId == song.id,
                                onPlayPause: { onPlayPause(song.id) },
                                onSelect: { onSongSelect(song.id) }
                            )
                            .transition(.opacity)
                        }
                    }
                    
                    // Action Buttons - Create More and Edit Lyrics (left-aligned, styled like reference) - only show on last song generation
                    if isLastSongGeneration {
                        HStack {
                            // Create More Button
                            Button(action: onCreateMore) {
                                HStack(spacing: 4) {
                                    Image.FigmaMCP.create
                                        .resizable()
                                        .renderingMode(.template)
                                        .frame(width: 16, height: 16)
                                        .foregroundColor(ChatConstants.Colors.Foreground.primary)
                                    
                                    Text("Create more")
                                        .figmaMCPTypography(TypographyV1.FigmaMCP.xSmallTitle)
                                        .kerning(0.24)
                                        .foregroundColor(ChatConstants.Colors.Foreground.primary)
                                }
                                .padding(.horizontal, 16)
                                .padding(.vertical, 6)
                                .frame(height: 32)
                                .background(
                                    RoundedRectangle(cornerRadius: 100)
                                        .fill(ChatConstants.Colors.Background.Fog.thin)
                                )
                            }
                            .buttonStyle(PlainButtonStyle())
                            
                            // Edit Lyrics Button (only show if lyrics exist)
                            if (songData?.lyrics ?? currentLyrics) != nil {
                                Button(action: onLyricsExpand) {
                                    HStack(spacing: 4) {
                                        Image.FigmaMCP.lyrics
                                            .resizable()
                                            .renderingMode(.template)
                                            .frame(width: 16, height: 16)
                                            .foregroundColor(ChatConstants.Colors.Foreground.primary)
                                        
                                        Text("Edit lyrics")
                                            .figmaMCPTypography(TypographyV1.FigmaMCP.xSmallTitle)
                                            .kerning(0.24)
                                            .foregroundColor(ChatConstants.Colors.Foreground.primary)
                                    }
                                    .padding(.horizontal, 16)
                                    .padding(.vertical, 6)
                                    .frame(height: 32)
                                    .background(
                                        RoundedRectangle(cornerRadius: 100)
                                            .fill(ChatConstants.Colors.Background.Fog.thin)
                                    )
                                }
                                .buttonStyle(PlainButtonStyle())
                            }
                            
                            Spacer()
                        }
                    }
                }
                .opacity(showSongs ? 1.0 : 0.0)
                .animation(.easeInOut(duration: 0.5), value: showSongs)
            }
        }
        .onAppear {
            if !hasAnimated {
                hasAnimated = true
                startAnimationSequence()
            } else {
                // If already animated, show all content immediately
                showMessage = !message.isEmpty
                showLyrics = (songData?.lyrics ?? currentLyrics) != nil
                showSongs = !songs.isEmpty
                typedMessage = message
            }
        }
    }
    
    private func startAnimationSequence() {
        // 1. Start typing animation immediately if there's a message
        // TODO: (JY) This needs some fixing
        if !message.isEmpty {
            showMessage = true
            startTypingAnimation()
        } else {
            // If no message, skip to lyrics
            startLyricsAnimation()
        }
    }
    
    private func startTypingAnimation() {
        let characters = Array(message)
        let totalDuration: Double = 0.8 // Fast typing - 0.8 seconds total
        let intervalPerCharacter = totalDuration / Double(characters.count)
        
        typedMessage = ""
        
        for (index, character) in characters.enumerated() {
            DispatchQueue.main.asyncAfter(deadline: .now() + intervalPerCharacter * Double(index)) {
                typedMessage += String(character)
                
                // When typing is complete, start lyrics animation
                if index == characters.count - 1 {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        startLyricsAnimation()
                    }
                }
            }
        }
    }
    
    private func startLyricsAnimation() {
        // 2. Fade in lyrics
        if (songData?.lyrics ?? currentLyrics) != nil {
            withAnimation(.easeInOut(duration: 0.3)) {
                showLyrics = true
            }
            
            // 3. After lyrics fade in, fade in songs
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
                startSongsAnimation()
            }
        } else {
            // If no lyrics, skip to songs
            startSongsAnimation()
        }
    }
    
    private func startSongsAnimation() {
        // 3. Simple fade in animation for songs
        if !songs.isEmpty {
            withAnimation(.easeInOut(duration: 0.3)) {
                showSongs = true
            }
        }
    }
}

struct SimpleSongCard: View {
    let song: Song
    let isPlaying: Bool
    let isSelected: Bool
    let onPlayPause: () -> Void
    let onSelect: () -> Void
    
    @ObservedObject private var audioManager = AudioManager.shared
    
    // Computed progress - reactive to audioManager updates
    private var progress: Double {
        (audioManager.currentlyPlayingSongId == song.id) ? audioManager.currentProgress : 0.0
    }

    var body: some View {
        VStack(spacing: 16) {
            // Album Artwork Section (Play/Pause tap area) - Square like reference
            Button(action: {
                // If song is not currently playing AND not selected, select it when starting playback
                if !isPlaying && !isSelected {
                    onSelect()
                }
                onPlayPause()
            }) {
                ZStack {
                    // Artwork with gradient - square aspect ratio
                    RoundedRectangle(cornerRadius: 24)
                        .fill(createGradientForSong(song))
                        .aspectRatio(1, contentMode: .fit)
                        .frame(maxWidth: 343)
                    
                    // Interactive waveform with pink progress line
                    let shouldShowWaveform = isPlaying || progress > 0.01 // ~1-2 seconds for typical song lengths
                    if shouldShowWaveform {
                        VStack {
                            Spacer()
                            
                            HStack {
                                Spacer()
                                
                                // Waveform with scrubbing
                                WaveformScrubber(
                                    progress: progress,
                                    onProgressChanged: { newProgress in
                                        if audioManager.currentlyPlayingSongId == song.id && audioManager.isCurrentlyPlaying {
                                            audioManager.seekToProgress(newProgress)
                                        }
                                    },
                                    onScrubStart: {
                                        if audioManager.currentlyPlayingSongId == song.id && audioManager.isCurrentlyPlaying {
                                            audioManager.startScrubbing()
                                        }
                                    },
                                    onScrubEnd: {
                                        if audioManager.currentlyPlayingSongId == song.id && audioManager.isCurrentlyPlaying {
                                            audioManager.endScrubbing()
                                        }
                                    }
                                )
                                .frame(width: 128, height: 24)
                                
                                Spacer()
                            }
                            .padding(.bottom, 16)
                        }
                    }
                    
                    // Play Button or Pause Button Overlay
                    if isPlaying {
                        // Pause Button
                        Image.FigmaMCP.pause
                            .figmaMCPIconStyle(
                                size: Image.FigmaMCPSize.large,
                                semanticColor: .white
                            )
                    } else {
                        Image.FigmaMCP.play
                            .figmaMCPIconStyle(
                                size: Image.FigmaMCPSize.large,
                                semanticColor: .white
                            )
                    }
                }
            }
            .buttonStyle(PlainButtonStyle())
            
            // Song Info Section (Selection tap area)
            Button(action: onSelect) {
                VStack(spacing: 8) {
                    // Song Info
                    VStack(spacing: 0) {
                        HStack {
                            Text(song.title)
                                .figmaMCPTypography(TypographyV1.FigmaMCP.smallTitle)
                                .kerning(0.24)
                                .foregroundColor(isSelected ? ChatConstants.Colors.Accent.brand : ChatConstants.Colors.Foreground.primary)
                            Spacer()
                        }
                        
                        HStack {
                            Text(song.genres.joined(separator: ", "))
                                .figmaMCPTypography(TypographyV1.FigmaMCP.small)
                                .kerning(0.24)
                                .foregroundColor(ChatConstants.Colors.Foreground.secondary.opacity(0.7))
                                .lineLimit(2)
                                .multilineTextAlignment(.leading)
                            Spacer()
                        }
                    }
                    
                    // Action Buttons (thumbs up, thumbs down, share, more)
                    HStack(spacing: 16) {
                        // Thumbs Up
                        Button(action: {
                            print("Thumbs up for: \(song.title)")
                        }) {
                            Image.FigmaMCP.thumbsUp
                                .resizable()
                                .renderingMode(.template)
                                .frame(width: 16, height: 16)
                                .foregroundColor(ChatConstants.Colors.Background.Fog.dense)
                        }
                        
                        // Thumbs Down
                        Button(action: {
                            print("Thumbs down for: \(song.title)")
                        }) {
                            Image.FigmaMCP.thumbsDown
                                .resizable()
                                .renderingMode(.template)
                                .frame(width: 16, height: 16)
                                .foregroundColor(ChatConstants.Colors.Background.Fog.dense)
                        }
                        
                        // Share
                        Button(action: {
                            print("Share: \(song.title)")
                        }) {
                            Image.FigmaMCP.shareArrow
                                .resizable()
                                .renderingMode(.template)
                                .frame(width: 16, height: 16)
                                .foregroundColor(ChatConstants.Colors.Background.Fog.dense)
                        }
                        
                        // More
                        Button(action: {
                            print("More options for: \(song.title)")
                        }) {
                            Image.FigmaMCP.moreHorizontal
                                .resizable()
                                .renderingMode(.template)
                                .frame(width: 16, height: 16)
                                .foregroundColor(ChatConstants.Colors.Background.Fog.dense)
                        }
                        
                        Spacer()
                    }
                }
                .padding(.horizontal, 8)
            }
            .buttonStyle(PlainButtonStyle())
        }
        .padding(.horizontal, 8)
        .padding(.top, 8)
        .padding(.bottom, 16)
        .frame(minWidth: 175)
        .fixedSize(horizontal: false, vertical: true)
        .background(
            RoundedRectangle(cornerRadius: 24)
                .fill(isSelected ? ChatConstants.Colors.Background.Fog.thin : Color.clear)
        )
    }
}

// MARK: - Waveform Component

struct WaveformScrubber: View {
    let progress: Double
    let onProgressChanged: (Double) -> Void
    let onScrubStart: () -> Void
    let onScrubEnd: () -> Void
    
    @State private var isScrubbing: Bool = false
    
    // Static waveform data - different heights between 4 and 24
    private let waveformHeights: [CGFloat] = [
        4, 8, 19, 15, 8, 19, 23, 6, 15, 21, 7, 16, 23, 23, 16, 8, 11, 12, 20, 7, 23, 15, 9, 21, 22, 21, 13, 15, 20, 9, 12, 20, 22, 22, 16, 6, 6, 11, 14, 19, 16, 20, 4
    ]
    
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                // Waveform bars
                HStack(spacing: 2) {
                    ForEach(0..<waveformHeights.count, id: \.self) { index in
                        let barProgress = Double(index) / Double(waveformHeights.count - 1)
                        let isPlayed = barProgress <= progress
                        
                        RoundedRectangle(cornerRadius: 0.5)
                            .fill(isPlayed ? Color.white : Color.white.opacity(0.3))
                            .frame(width: 1, height: waveformHeights[index])
                    }
                }
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
                
                // Pink progress line
                RoundedRectangle(cornerRadius: 1)
                    .fill(ChatConstants.Colors.Accent.brand)
                    .frame(width: 2, height: 24)
                    .position(
                        x: geometry.size.width * CGFloat(progress),
                        y: geometry.size.height / 2
                    )
                    .allowsHitTesting(false)
                
                // Invisible drag area for scrubbing
                Rectangle()
                    .fill(Color.clear)
                    .contentShape(Rectangle())
                    .gesture(
                        DragGesture(minimumDistance: 0)
                            .onChanged { value in
                                // Only call onScrubStart once at the beginning of the drag
                                if !isScrubbing {
                                    isScrubbing = true
                                    onScrubStart()
                                }
                                let newProgress = max(0, min(1, value.location.x / geometry.size.width))
                                onProgressChanged(newProgress)
                            }
                            .onEnded { _ in
                                isScrubbing = false
                                onScrubEnd()
                            }
                    )
            }
        }
    }
}

private func createGradientForSong(_ song: Song) -> LinearGradient {
    guard let artwork = song.artwork else {
        return LinearGradient(
            colors: [
                ChatConstants.Colors.Accent.purple,
                ChatConstants.Colors.Accent.pink
            ],
            startPoint: .topLeading,
            endPoint: .bottomTrailing
        )
    }

    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 {
    let sampleMessages: IdentifiedArrayOf<ChatMessage> = [
        ChatMessage(content: "I want to make a song about my best friend", isOutgoing: true),
        ChatMessage(content: "Great choice! I'll create an upbeat song about friendship.\nLet me work on some lyrics for you.", isOutgoing: false),
        ChatMessage(content: "Can you make it more emotional and heartfelt?", isOutgoing: true),
        ChatMessage(content: "Here you go, I made two versions of the song.\nLet me know what you want to make edits, I can also\ncreate more versions.", isOutgoing: false),
        ChatMessage(content: "I love the second version! Can you add a bridge section?", isOutgoing: true),
        ChatMessage(content: "Absolutely! Here's the song with an added bridge:\n\nVerse 1:\nWe've been through it all together\nThrough the storms and sunny weather\n\nChorus:\nYou're my best friend, through and through\nThere's nothing that we can't get through\n\nBridge:\nWhen the world gets heavy on my shoulders\nYou remind me that we're getting older\nBut our friendship stays forever young\nThis is our song, and it's just begun", isOutgoing: false)
    ]
    
    ChatsView(
        messages: sampleMessages,
        currentlyPlayingSongId: nil,
        currentlySelectedSongId: nil,
        isLoading: false,
        onSongPlayPause: { songId in
            print("Play/Pause song: \(songId)")
        },
        onSongSelect: { songId in
            print("Select song: \(songId)")
        },
        onCreateMore: {
            print("Create more tapped")
        },
        onLyricsExpand: {
            print("Lyrics expand tapped")
        },
        onLinkTap: { url in
            print("Link tapped: \(url)")
        },
        shouldAutoScroll: false
    )
    .background(ChatConstants.Colors.Background.primary)
}

// MARK: - Lyrics Views

struct InlineLyricsView: View {
    let lyrics: String
    let isExpanded: Bool
    let onSeeMoreTap: () -> Void

    var body: some View {
        VStack(spacing: 12) {
            // Header
            HStack {
                Text("Lyrics")
                    .figmaMCPTypography(TypographyV1.FigmaMCP.mediumRegular)
                    .kerning(0.32)
                    .foregroundColor(ChatConstants.Colors.Foreground.primary)

                Spacer()
            }

            // Lyrics Content
            // Section content
            Text(lyrics)
                .figmaMCPTypography(TypographyV1.FigmaMCP.mediumRegular)
                .kerning(0.32)
                .foregroundColor(ChatConstants.Colors.Foreground.tertiary)
                .lineLimit(isExpanded ? nil : 4)
                .multilineTextAlignment(.leading)
                .frame(maxWidth: .infinity, alignment: .leading)

//            VStack(alignment: .leading, spacing: 12) {
//                ForEach(Array(displaySections.enumerated()), id: \.offset) { index, section in
//                    VStack(alignment: .leading, spacing: 4) {
//                        // Section label (e.g., [Chorus], [Verse 1])
//                        Text("[\(section.type)]")
//                            .figmaMCPTypography(TypographyV1.FigmaMCP.mediumRegular)
//                            .kerning(0.32)
//                            .foregroundColor(ChatConstants.Colors.Foreground.tertiary)
//
//                        // Section content
//                        Text(section.content)
//                            .figmaMCPTypography(TypographyV1.FigmaMCP.mediumRegular)
//                            .kerning(0.32)
//                            .foregroundColor(ChatConstants.Colors.Foreground.tertiary)
//                            .lineLimit(isExpanded ? nil : 4)
//                            .multilineTextAlignment(.leading)
//                    }
//                    .frame(maxWidth: .infinity, alignment: .leading)
//                }
//
//                 See more/less button
//                if hasMoreContent {
//                    Button(action: onSeeMoreTap) {
//                        HStack {
//                            Text(isExpanded ? "See less" : "See more")
//                                .figmaMCPTypography(TypographyV1.FigmaMCP.mediumTitle)
//                                .kerning(0.32)
//                                .foregroundColor(ChatConstants.Colors.Accent.brand)
//                            Spacer()
//                        }
//                    }
//                }
//            }
//            .frame(maxWidth: .infinity, alignment: .leading)
        }
        .padding(16)
        .background(
            RoundedRectangle(cornerRadius: 16)
                .fill(ChatConstants.Colors.Background.Fog.thin)
        )
    }

//    private var displaySections: [LyricsSection] {
//        if isExpanded {
//            return lyrics.sections
//        } else {
//            // Show only first 2 sections when collapsed
//            return Array(lyrics.sections.prefix(2))
//        }
//    }
//
//    private var hasMoreContent: Bool {
//        lyrics.sections.count > 2
//    }
}
