import ComponentLibrary
import SwiftUI

public struct WaveformStripTimeControls: View {
    let width: CGFloat
    let height: CGFloat
    let markerTime: String
    let leftEdgeTime: String
    let rightEdgeTime: String
    let isFineScrubbing: Bool
    let showLeftEdgeArrow: Bool
    let showRightEdgeArrow: Bool
    let onTapMarkerTime: () -> Void
    let onTapLeftEdgeArrow: () -> Void
    let onTapRightEdgeArrow: () -> Void
    let onHoldLeftEdgeArrow: () -> Void
    let onHoldRightEdgeArrow: () -> Void
    let onHoldEnd: () -> Void
    let isHighlightedPortionToTheRightOfVisibleWindow: Bool
    let isHighlightedPortionToTheLeftOfVisibleWindow: Bool
    let onTapRecenterToHighlightedPortion: () -> Void
    @State private var hapticProxy: Int = .zero
    // Helpers to determine when we're holding the controls
    @State private var isHoldingLeftArrow: Bool = false
    @State private var isHoldingRightArrow: Bool = false
    @State private var leftArrowTimer: Timer?
    @State private var rightArrowTimer: Timer?

    // Arrow buttons to seek time on the waveform strip
    private func arrowButton(
        isLeftArrow: Bool,
        isHighlightedPortionOutside: Bool,
        onTap: @escaping () -> Void
    ) -> some View {
        Button {
            if isHighlightedPortionOutside {
                onTapRecenterToHighlightedPortion()
            } else {
                onTap()
                hapticProxy += 1
            }
        } label: {
            Image(systemName: "chevron.\(isLeftArrow ? "left" : "right")")
                .font(.system(size: 10, weight: .semibold))
                .foregroundColor(isHighlightedPortionOutside ? Color.SemanticV1.iconLink : Color.SemanticV1.textSecondary)
                .frame(width: 10, height: 10)
                .padding(.leading, isLeftArrow ? 8 : 0)
                .padding(.trailing, isLeftArrow ? 0 : 8)
        }
        .contentShape(.rect)
        .buttonStyle(ScaleButtonStyle())
        .frame(maxWidth: .infinity, alignment: isLeftArrow ? .leading : .trailing)
        .simultaneousGesture(
            DragGesture(minimumDistance: 0)
                .onChanged { _ in
                    guard !isHighlightedPortionOutside else { return }
                    startArrowTimer(isLeftArrow: isLeftArrow)
                }
                .onEnded { _ in
                    cancelArrowTimer(isLeftArrow: isLeftArrow)
                }
        )
    }

    // Detect if we're holding the arrow button
    private func startArrowTimer(isLeftArrow: Bool) {
        let isHolding = isLeftArrow ? isHoldingLeftArrow : isHoldingRightArrow
        guard !isHolding else { return }

        let timer = isLeftArrow ? leftArrowTimer : rightArrowTimer
        timer?.invalidate()

        let newTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
            if isLeftArrow {
                isHoldingLeftArrow = true
                onHoldLeftEdgeArrow()
            } else {
                isHoldingRightArrow = true
                onHoldRightEdgeArrow()
            }
            hapticProxy += 1
        }

        if isLeftArrow {
            leftArrowTimer = newTimer
        } else {
            rightArrowTimer = newTimer
        }
    }

    // Cancel the arrow timer
    private func cancelArrowTimer(isLeftArrow: Bool) {
        let timer = isLeftArrow ? leftArrowTimer : rightArrowTimer
        timer?.invalidate()
        if isLeftArrow {
            leftArrowTimer = nil
            guard isHoldingLeftArrow else { return }
            isHoldingLeftArrow = false
        } else {
            rightArrowTimer = nil
            guard isHoldingRightArrow else { return }
            isHoldingRightArrow = false
        }
        onHoldEnd()
    }

    public var body: some View {
        VStack(spacing: 0) {
            Rectangle().frame(width: width, height: height).foregroundColor(.clear)
            Rectangle().frame(height: 1).foregroundColor(.SemanticV1.backgroundTertiary)
            ZStack(alignment: .center) {
                if isFineScrubbing {
                    Text(leftEdgeTime)
                        .typographyV1(.subtitleSmall)
                        .foregroundColor(Color.SemanticV1.textSecondary)
                        .transition(.opacity)
                        .padding(.leading, 10)
                        .frame(maxWidth: .infinity, alignment: .leading)

                    HStack {
                        Spacer()
                        Text(rightEdgeTime)
                            .typographyV1(.subtitleSmall.neueMontrealMedium())
                            .foregroundColor(Color.SemanticV1.textSecondary)
                            .transition(.opacity)
                            .frame(width: 46, alignment: .leading)
                    }
                    .frame(maxWidth: .infinity, alignment: .trailing)
                }
                arrowButton(
                    isLeftArrow: true,
                    isHighlightedPortionOutside: isHighlightedPortionToTheLeftOfVisibleWindow,
                    onTap: onTapLeftEdgeArrow
                )
                .opacity(showLeftEdgeArrow ? 1.0 : 0.0)
                arrowButton(
                    isLeftArrow: false,
                    isHighlightedPortionOutside: isHighlightedPortionToTheRightOfVisibleWindow,
                    onTap: onTapRightEdgeArrow
                )
                .opacity(showRightEdgeArrow ? 1.0 : 0.0)
                Text(markerTime)
                    .typographyV1(.subtitleSmall)
                    .foregroundColor(Color.SemanticV1.textSecondary)
                    .frame(width: 70, alignment: .leading)
                    .padding(.leading, 32)
                    .contentShape(.rect)
                    .onTapGesture {
                        onTapMarkerTime()
                        hapticProxy += 1
                    }
            }
            .frame(height: 20)
            Rectangle().frame(height: 1).foregroundColor(.SemanticV1.backgroundTertiary)
        }
        .animation(.easeInOut(duration: 0.1), value: isFineScrubbing)
        .sensoryFeedbackIfEnabled(.selection, trigger: hapticProxy)
    }
}
