import SwiftUI

// MARK: - MultiTrackTimeline
/// A three-track horizontal timeline visualization showing:
/// - Track 1: Audio availability and silence markers
/// - Track 2: Photo markers (camera outlines at event positions)
/// - Track 3: Note/marker outline icons at event positions
/// Includes a time ruler and a central playhead cursor.
/// Fully redesigned with a minimalist business line-drawn style.
struct MultiTrackTimeline: View {
    let events: [CelestiaTimelineEvent]
    @Binding var currentTimeMs: Double
    let totalDurationMs: Double
    var waveformSamples: [Float] = []
    var silentRanges: [SilenceRange] = []

    @State private var playheadDragStartTimeMs: Double?

    /// Scale: points per second
    private let pointsPerSecond: CGFloat = 2.5
    /// Minimum timeline width
    private let minimumWidth: CGFloat = 400

    private var timelineWidth: CGFloat {
        max(minimumWidth, CGFloat(totalDurationMs / 1000.0) * pointsPerSecond + 60)
    }

    var body: some View {
        VStack(spacing: 0) {
            ScrollViewReader { scrollProxy in
                ScrollView(.horizontal, showsIndicators: false) {
                    ZStack(alignment: .topLeading) {
                        // Background
                        RoundedRectangle(cornerRadius: 10)
                            .fill(Color.cardBackground.opacity(0.15))

                        VStack(spacing: 0) {
                            // Time Ruler
                            timeRuler
                                .frame(height: 26)

                            // Track 1: Audio Waveform
                            audioTrack
                                .frame(height: 38)

                            trackDivider

                            // Track 2: Photo Markers
                            photoTrack
                                .frame(height: 28)

                            trackDivider

                            // Track 3: Note Markers
                            noteTrack
                                .frame(height: 28)
                        }

                        // Playhead Cursor
                        playhead
                            .id("playhead")
                    }
                    .frame(width: timelineWidth)
                }
                .clipShape(RoundedRectangle(cornerRadius: 10))
                .businessBorder(cornerRadius: 10)
                .onChange(of: currentTimeMs) { _, _ in
                    guard playheadDragStartTimeMs == nil else { return }
                    withAnimation(.easeOut(duration: 0.2)) {
                        scrollProxy.scrollTo("playhead", anchor: .center)
                    }
                }
            }

            // Track labels
            trackLabels
                .padding(.top, 8)
        }
    }

    // MARK: - Time Ruler

    private var timeRuler: some View {
        Canvas { context, size in
            let totalSeconds = totalDurationMs / 1000.0
            let markerInterval: Double = totalSeconds > 300 ? 60 : (totalSeconds > 60 ? 10 : 5)

            var t: Double = 0
            while t <= totalSeconds {
                let x = xPosition(for: t * 1000)

                // Tick mark
                let tickPath = Path { path in
                    path.move(to: CGPoint(x: x, y: size.height - 6))
                    path.addLine(to: CGPoint(x: x, y: size.height))
                }
                context.stroke(tickPath, with: .color(Color.primary.opacity(0.2)), lineWidth: 1)

                // Time label
                let minutes = Int(t) / 60
                let seconds = Int(t) % 60
                let label = String(format: "%d:%02d", minutes, seconds)

                let text = Text(label)
                    .font(.system(size: 8, weight: .regular, design: .monospaced))
                    .foregroundStyle(Color.secondary.opacity(0.8))

                context.draw(
                    context.resolve(text),
                    at: CGPoint(x: x, y: size.height - 14),
                    anchor: .center
                )

                t += markerInterval
            }
        }
    }

    // MARK: - Audio Track

    private var audioTrack: some View {
        Canvas { context, size in
            let centerY = size.height / 2
            let barWidth: CGFloat = 1
            let barSpacing: CGFloat = 2
            let barSlot = barWidth + barSpacing
            let startX = xPosition(for: 0)
            let endX = xPosition(for: totalDurationMs)
            let waveformWidth = max(0, endX - startX)
            let barCount = max(0, Int(waveformWidth / barSlot))

            for range in silentRanges {
                let rangeStart = max(startX, xPosition(for: range.start * 1000))
                let rangeEnd = min(endX, xPosition(for: range.end * 1000))
                guard rangeEnd > rangeStart else { continue }
                context.fill(
                    Path(CGRect(
                        x: rangeStart,
                        y: 0,
                        width: rangeEnd - rangeStart,
                        height: size.height
                    )),
                    with: .color(Color.secondary.opacity(0.10))
                )
            }

            let centerLine = Path { path in
                path.move(to: CGPoint(x: startX, y: centerY))
                path.addLine(to: CGPoint(x: endX, y: centerY))
            }
            context.stroke(
                centerLine,
                with: .color(Color.primary.opacity(0.1)),
                lineWidth: 1
            )

            guard barCount > 0, !waveformSamples.isEmpty else { return }

            for index in 0..<barCount {
                let sampleStart = index * waveformSamples.count / barCount
                let sampleEnd = max(
                    sampleStart + 1,
                    (index + 1) * waveformSamples.count / barCount
                )
                let upperBound = min(sampleEnd, waveformSamples.count)
                guard sampleStart < upperBound else { continue }

                let amplitude = waveformSamples[sampleStart..<upperBound].max() ?? 0
                let barHeight = max(CGFloat(max(amplitude, 0)) * size.height * 0.75, 1)
                let rect = CGRect(
                    x: startX + CGFloat(index) * barSlot,
                    y: centerY - barHeight / 2,
                    width: barWidth,
                    height: barHeight
                )
                context.fill(
                    Path(rect),
                    with: .color(Color.primary.opacity(0.85))
                )
            }
        }
    }

    // MARK: - Photo Track

    private var photoTrack: some View {
        ZStack(alignment: .leading) {
            Color.clear

            ForEach(photoEvents) { event in
                Image(systemName: "camera")
                    .font(.system(size: 9))
                    .foregroundStyle(Color.primary.opacity(0.8))
                    .frame(width: 20, height: 20)
                    .background(Color.cardBackground.opacity(0.6))
                    .businessBorder(cornerRadius: 10)
                    .offset(x: xPosition(for: Double(event.relativeTimeMs)) - 10)
            }
        }
    }

    // MARK: - Note Track

    private var noteTrack: some View {
        ZStack(alignment: .leading) {
            Color.clear

            ForEach(noteEvents) { event in
                let iconName = event.eventType == "MARKER" ? "exclamationmark.triangle" : "doc.text"
                Image(systemName: iconName)
                    .font(.system(size: 9))
                    .foregroundStyle(Color.primary.opacity(0.8))
                    .frame(width: 20, height: 20)
                    .background(Color.cardBackground.opacity(0.6))
                    .businessBorder(cornerRadius: 10)
                    .offset(x: xPosition(for: Double(event.relativeTimeMs)) - 10)
            }
        }
    }

    // MARK: - Playhead

    private var playhead: some View {
        let x = xPosition(for: currentTimeMs)
        return ZStack {
            Color.clear
                .contentShape(Rectangle())

            Rectangle()
                .fill(Color.primary)
                .frame(width: 1)
        }
            .frame(width: 28)
            .offset(x: x - 14)
            .animation(
                playheadDragStartTimeMs == nil ? .easeOut(duration: 0.15) : nil,
                value: currentTimeMs
            )
            .highPriorityGesture(playheadDragGesture)
            .accessibilityLabel("当前播放位置")
            .accessibilityValue(formattedTime(currentTimeMs))
            .accessibilityAdjustableAction { direction in
                let stepMs = 1_000.0
                switch direction {
                case .increment:
                    currentTimeMs = min(totalDurationMs, currentTimeMs + stepMs)
                case .decrement:
                    currentTimeMs = max(0, currentTimeMs - stepMs)
                @unknown default:
                    break
                }
            }
    }

    private var playheadDragGesture: some Gesture {
        DragGesture(minimumDistance: 0, coordinateSpace: .global)
            .onChanged { value in
                let startTime = playheadDragStartTimeMs ?? currentTimeMs
                if playheadDragStartTimeMs == nil {
                    playheadDragStartTimeMs = startTime
                }

                let startX = xPosition(for: startTime)
                currentTimeMs = timeMs(forXPosition: startX + value.translation.width)
            }
            .onEnded { _ in
                playheadDragStartTimeMs = nil
            }
    }

    // MARK: - Track Divider

    private var trackDivider: some View {
        Rectangle()
            .fill(Color.lineBorder)
            .frame(height: 1)
    }

    // MARK: - Track Labels

    private var trackLabels: some View {
        HStack(spacing: 24) {
            trackLabel(icon: "waveform", text: "音频")
            trackLabel(icon: "camera", text: "图片")
            trackLabel(icon: "doc.text", text: "笔记")
        }
    }

    private func trackLabel(icon: String, text: String) -> some View {
        HStack(spacing: 4) {
            Image(systemName: icon)
                .font(.system(size: 9, weight: .light))
            Text(text)
                .font(.system(size: 9, weight: .regular))
        }
        .foregroundStyle(Color.secondary)
    }

    // MARK: - Helpers

    private func xPosition(for timeMs: Double) -> CGFloat {
        guard totalDurationMs > 0 else { return 30 }
        let padding: CGFloat = 30
        let usableWidth = timelineWidth - padding * 2
        let ratio = min(max(timeMs / totalDurationMs, 0), 1)
        return padding + usableWidth * CGFloat(ratio)
    }

    private func timeMs(forXPosition x: CGFloat) -> Double {
        guard totalDurationMs > 0 else { return 0 }
        let padding: CGFloat = 30
        let usableWidth = timelineWidth - padding * 2
        guard usableWidth > 0 else { return 0 }
        let ratio = min(max((x - padding) / usableWidth, 0), 1)
        return Double(ratio) * totalDurationMs
    }

    private func formattedTime(_ timeMs: Double) -> String {
        let totalSeconds = max(0, Int(timeMs / 1_000))
        return String(format: "%d:%02d", totalSeconds / 60, totalSeconds % 60)
    }

    private var photoEvents: [CelestiaTimelineEvent] {
        events.filter { $0.eventType == "PHOTO" }
    }

    private var noteEvents: [CelestiaTimelineEvent] {
        events.filter { $0.eventType == "NOTE" || $0.eventType == "MARKER" }
    }
}

// MARK: - Preview

#Preview {
    VStack {
        MultiTrackTimeline(
            events: [],
            currentTimeMs: .constant(30000),
            totalDurationMs: 120000,
            waveformSamples: [0.1, 0.3, 0.8, 0.4, 0.2]
        )
        .frame(height: 140)
        .padding()
    }
    .background(Color.spaceBlack)
}
