import APIClient
import Foundation
import Localization
import SwiftUI
import Utilities

public struct HookVideoCellSongCapsule: View {
    let hook: Hook
    let playbackState: PlaybackState
    let isClipLiked: Bool
    let clipPlayCount: Int
    let onAddSongTapped: (Hook) -> Void
    let onChangePlaylistTapped: (Hook) -> Void
    let onSongTapped: (Clip) -> Void
    @State private var isAnimatingWaveform: Bool = false
    @State private var rotationAngle: Double = 0
    @State private var spinTimer: Timer?
    @State private var showLikedToast: Bool = false
    @State private var didTapAddSongToLikes: Bool = false
    @Namespace private var animation

    public init(
        hook: Hook,
        playbackState: PlaybackState,
        isClipLiked: Bool,
        clipPlayCount: Int,
        onAddSongTapped: @escaping (Hook) -> Void,
        onChangePlaylistTapped: @escaping (Hook) -> Void,
        onSongTapped: @escaping (Clip) -> Void
    ) {
        self.hook = hook
        self.playbackState = playbackState
        self.isClipLiked = isClipLiked
        self.clipPlayCount = clipPlayCount
        self.onAddSongTapped = onAddSongTapped
        self.onChangePlaylistTapped = onChangePlaylistTapped
        self.onSongTapped = onSongTapped
    }

    public var body: some View {
        ZStack {
            Button(action: {
                guard let clip = hook.clip else { return }
                onSongTapped(clip)
            }) {
                if #available(iOS 26.0, *) {
                    capsule
                        .clipShape(.capsule)
                        .glassEffect(.regular, in: .capsule)
                        .padding([.horizontal, .bottom], 8)
                        .contentShape(Rectangle())
                } else {
                    capsule
                        .background(.ultraThinMaterial)
                        .clipShape(.capsule)
                        .padding([.horizontal, .bottom], 8)
                        .contentShape(Rectangle())
                }
            }
            .buttonStyle(ScaleButtonStyle(scaleAmount: 0.95))
            .transition(.opacity)

            addSongToast
                .opacity(showLikedToast ? 1 : 0)
                .animation(.easeInOut(duration: 0.3), value: showLikedToast)
                .allowsHitTesting(showLikedToast)
        }
        .onChange(of: isClipLiked) { _, newValue in
            if newValue && didTapAddSongToLikes {
                handleLikedStateChange()
            }
        }
    }

    private var capsule: some View {
        HStack(spacing: 0) {
            songArtDisc
                .padding(.trailing, 8)
            header
            Spacer()
            addSongButton
        }
        .padding(8)
        .background {
            ZStack {
                RemoteImage(url: hook.clip?.largeImageUrl, fallbackId: nil)
                    .blur(radius: 22)
                    .overlay {
                        Rectangle()
                            .foregroundStyle(blurOverlayColor)
                    }
                    .opacity(0.5)
            }
        }
    }

    @ViewBuilder
    private var addSongToast: some View {
        Button(action: {}) {
            HStack(spacing: 0) {
                HStack(spacing: 8) {
                    Image.Icon.thumbsUp
                        .renderingMode(.template)
                        .frame(width: 24, height: 24)
                        .foregroundStyle(Color.SemanticV2.foregroundPrimary)
                    Text(L10n.FeatureHooks.addedToLikedSongs)
                        .foregroundStyle(.white)
                        .typographyV1(.button.neueMontrealRegular().kerning(0.28))
                }

                Spacer()

                Button(action: {
                    onChangePlaylistTapped(hook)
                }) {
                    Text(L10n.FeatureHooks.change)
                        .foregroundStyle(Color.SemanticV2.accentPink)
                        .typographyV1(.caption4.kerning(0.24))
                        .padding(4)
                }
            }
        }
        .padding(.vertical, 18)
        .padding(.leading, 20)
        .padding(.trailing, 24)
        .background {
            Color.SemanticV2.backgroundSecondary
        }
        .clipShape(RoundedRectangle(cornerRadius: 40))
        .padding([.horizontal, .bottom], 8)
        .contentShape(Rectangle())
        .transition(.opacity)
        .allowsHitTesting(true)
    }

    @ViewBuilder
    private var songArtDisc: some View {
        ZStack {
            // Spinning disc (image + background)
            RemoteImage(url: hook.clip?.largeImageUrl, fallbackId: nil)
                .frame(width: 44, height: 44)
                .cornerRadius(.infinity)
                .background {
                    Circle()
                        .fill(Color.SemanticV2.backgroundFogThin)
                        .strokeBorder(Color.SemanticV2.backgroundGlassDense, lineWidth: 1, antialiased: false)
                }
                .rotationEffect(.degrees(rotationAngle))
                .animation(.linear, value: rotationAngle)

            Waveform(isAnimating: isAnimatingWaveform, barHeight: 10)
                .environment(\.colorScheme, .dark)
                .transition(.opacity)
                .onDisappear {
                    isAnimatingWaveform = false
                    spinTimer?.invalidate()
                    spinTimer = nil
                }
                .onAppear {
                    let isPlaying = playbackState == .playing
                    isAnimatingWaveform = isPlaying
                    toggleSpinAnimation(isPlaying: isPlaying)
                }
                .onChange(of: playbackState) { _, newState in
                    let isPlaying = newState == .playing
                    isAnimatingWaveform = isPlaying
                    toggleSpinAnimation(isPlaying: isPlaying)
                }
        }
    }

    @ViewBuilder
    private var addSongButton: some View {
        Button(action: {
            onAddSongTapped(hook)
            didTapAddSongToLikes = true
        }) {
            if isClipLiked {
                Circle()
                    .fill(Color.SemanticV2.backgroundFogThin)
                    .frame(width: 44, height: 44)
                    .overlay {
                        Image.Icon.checkV1
                            .resizable()
                            .foregroundStyle(Color.SemanticV2.accentPink)
                            .frame(width: 24, height: 24)
                    }
            } else {
                HStack(spacing: 6) {
                    Image.Icon.plus
                        .resizable()
                        .foregroundStyle(.white)
                        .frame(width: 18.0, height: 18.0)
                    Text(L10n.FeatureClipDetail.save.uppercased())
                        .foregroundStyle(.white)
                        .typographyV1(.monospace.lineHeight(18.0))
                }
                .padding(.horizontal, 16)
                .padding(.vertical, 4)
                .frame(height: 44)
                .background(RoundedRectangle(cornerRadius: 100).fill(Color.SemanticV2.backgroundFogThin))
            }
        }
        .animation(.easeInOut(duration: 0.2), value: isClipLiked)
    }

    private func handleLikedStateChange() {
        withAnimation(.easeInOut(duration: 0.3)) {
            showLikedToast = true
        }

        Task {
            try? await Task.sleep(nanoseconds: 5_000_000_000)
            await MainActor.run {
                withAnimation(.easeInOut(duration: 0.3)) {
                    showLikedToast = false
                }
            }
        }
    }

    @ViewBuilder
    private var headerScrollingTitleBar: some View {
        MarqueeText(
            text: hook.clip?.title ?? "",
            font: TypographyV1.body1.size { _ in 14.0 }.lineHeight(18.0).uiFont ?? .systemFont(ofSize: 14),
            leftFade: 4,
            rightFade: 4,
            startDelay: 1,
            alignment: .leading
        )
    }

    @ViewBuilder
    private var headerScrollingAuthorBar: some View {
        MarqueeText(
            text: hook.clip?.displayName ?? "",
            font: TypographyV1.body1.size { _ in 14.0 }.lineHeight(16.0).uiFont ?? .systemFont(ofSize: 14),
            leftFade: 4,
            rightFade: 4,
            startDelay: 1,
            alignment: .leading
        )
    }

    @ViewBuilder
    private var header: some View {
        VStack(alignment: .leading, spacing: 2) {
            headerScrollingTitleBar
                .foregroundStyle(.white)
            HStack(spacing: 0) {
                Image.Icon.playFilled
                    .resizable()
                    .frame(width: 10.0, height: 10.0)
                    .foregroundColor(.SemanticV1.iconPrimary)
                    .padding(.trailing, 4)
                Text(clipPlayCount.formatted(.number.notation(.compactName)))
                    .typographyV1(.monospace.size { _ in 11.0 }.lineHeight(13.0))
                    .padding(.bottom, -1)
                    .contentTransition(.numericText())
                    .animation(.easeInOut(duration: 0.3), value: clipPlayCount)
                Text("•")
                    .typographyV1(.body1.size { _ in 14.0 }.lineHeight(16.0))
                    .padding(.horizontal, 5)
                headerScrollingAuthorBar
            }
            .foregroundStyle(.white.opacity(0.7))
        }
    }

    private func toggleSpinAnimation(isPlaying: Bool) {
        // Stop any existing timer first
        spinTimer?.invalidate()
        spinTimer = nil

        if isPlaying {
            spinTimer = Timer.scheduledTimer(withTimeInterval: 0.016, repeats: true) { _ in
                rotationAngle += 0.857 // ~51.43 degrees per second = 7 second rotation (from spec)
            }
        } else {
            withAnimation(.easeOut(duration: 0.2)) {
                rotationAngle += 18
            }
        }
    }

    private let blurOverlayColor: Color = Color(uiColor: UIColor(red: 0.19, green: 0.19, blue: 0.19, alpha: 0.5))
}
