//
// OpenRocky — Voice-first AI Agent
// https://github.com/openrocky
//
// Developed by everettjf with the assistance of Claude Code and Codex.
// Copyright (c) 2026 everettjf. All rights reserved.
//

import SwiftUI

/// Full-screen media player sheet. Reads live state from OpenRockyMediaPlayerService.
struct OpenRockyMediaPlayerSheet: View {
    @ObservedObject private var service = OpenRockyMediaPlayerService.shared
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                nowPlayingCard
                controls
                playlistList
            }
            .padding(.top, 8)
            .navigationTitle("Now Playing")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        dismiss()
                    } label: {
                        Image(systemName: "xmark.circle.fill")
                            .font(.system(size: 20))
                            .symbolRenderingMode(.hierarchical)
                            .foregroundStyle(.secondary)
                    }
                }
            }
        }
    }

    // MARK: - Sections

    private var nowPlayingCard: some View {
        VStack(spacing: 14) {
            ZStack {
                RoundedRectangle(cornerRadius: 18, style: .continuous)
                    .fill(LinearGradient(
                        colors: [Color.blue.opacity(0.22), Color.purple.opacity(0.22)],
                        startPoint: .topLeading, endPoint: .bottomTrailing
                    ))
                Image(systemName: currentItemIcon)
                    .font(.system(size: 56, weight: .regular))
                    .foregroundStyle(.white.opacity(0.82))
            }
            .frame(width: 200, height: 200)
            .shadow(color: .black.opacity(0.25), radius: 12, y: 8)

            VStack(spacing: 4) {
                Text(currentFilename)
                    .font(.system(size: 17, weight: .bold, design: .rounded))
                    .multilineTextAlignment(.center)
                    .lineLimit(2)
                Text(subtitleText)
                    .font(.system(size: 12, weight: .medium))
                    .foregroundStyle(.secondary)
            }
            .padding(.horizontal, 24)

            progressBar
                .padding(.horizontal, 24)
        }
        .padding(.vertical, 16)
    }

    private var progressBar: some View {
        VStack(spacing: 4) {
            GeometryReader { proxy in
                ZStack(alignment: .leading) {
                    Capsule()
                        .fill(Color.secondary.opacity(0.2))
                        .frame(height: 4)
                    Capsule()
                        .fill(Color.accentColor)
                        .frame(width: max(0, proxy.size.width * progressFraction), height: 4)
                }
            }
            .frame(height: 4)
            HStack {
                Text(Self.formatTime(service.position))
                Spacer()
                Text(service.duration > 0 ? Self.formatTime(service.duration) : "--:--")
            }
            .font(.system(size: 11, design: .monospaced))
            .foregroundStyle(.secondary)
        }
    }

    private var controls: some View {
        VStack(spacing: 14) {
            HStack(spacing: 32) {
                iconButton(systemName: "backward.fill", size: 24) {
                    try? service.previous()
                }
                playPauseButton
                iconButton(systemName: "forward.fill", size: 24) {
                    try? service.next()
                }
            }

            HStack(spacing: 10) {
                ForEach([OpenRockyMediaPlaybackMode.sequential, .loop, .random, .repeatOne], id: \.rawValue) { mode in
                    modePill(mode)
                }
            }
            .padding(.top, 4)

            Button(role: .destructive) {
                service.stop()
            } label: {
                Label("Stop", systemImage: "stop.circle")
                    .font(.system(size: 14, weight: .medium))
            }
            .padding(.top, 4)
        }
        .padding(.vertical, 16)
    }

    private var playPauseButton: some View {
        Button {
            if service.isPlaying { service.pause() } else { service.resume() }
        } label: {
            ZStack {
                Circle()
                    .fill(Color.accentColor)
                    .frame(width: 64, height: 64)
                    .shadow(color: .black.opacity(0.3), radius: 8, y: 4)
                Image(systemName: service.isPlaying ? "pause.fill" : "play.fill")
                    .font(.system(size: 28, weight: .bold))
                    .foregroundStyle(.white)
                    .offset(x: service.isPlaying ? 0 : 2)
            }
        }
        .buttonStyle(.plain)
    }

    private func iconButton(systemName: String, size: CGFloat, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Image(systemName: systemName)
                .font(.system(size: size, weight: .medium))
                .foregroundStyle(.primary)
                .frame(width: 44, height: 44)
        }
        .buttonStyle(.plain)
    }

    private func modePill(_ mode: OpenRockyMediaPlaybackMode) -> some View {
        let active = service.mode == mode
        return Button {
            service.setMode(mode)
        } label: {
            HStack(spacing: 4) {
                Image(systemName: iconFor(mode))
                    .font(.system(size: 11, weight: .semibold))
                Text(labelFor(mode))
                    .font(.system(size: 12, weight: .semibold, design: .rounded))
            }
            .padding(.horizontal, 10)
            .padding(.vertical, 6)
            .background(
                Capsule().fill(active ? Color.accentColor.opacity(0.18) : Color.gray.opacity(0.12))
            )
            .foregroundStyle(active ? Color.accentColor : Color.secondary)
        }
        .buttonStyle(.plain)
    }

    private var playlistList: some View {
        List {
            Section {
                ForEach(Array(service.playlist.enumerated()), id: \.element.id) { idx, item in
                    Button {
                        jumpTo(index: idx)
                    } label: {
                        HStack(spacing: 10) {
                            Image(systemName: idx == service.currentIndex ? "waveform" : (item.kind == .video ? "video" : "music.note"))
                                .foregroundStyle(idx == service.currentIndex ? Color.accentColor : .secondary)
                                .frame(width: 22)
                            Text(item.filename)
                                .font(.system(size: 14, design: .rounded))
                                .foregroundStyle(idx == service.currentIndex ? Color.accentColor : .primary)
                                .lineLimit(1)
                            Spacer()
                            Text(item.kind.rawValue.uppercased())
                                .font(.system(size: 9, weight: .bold, design: .monospaced))
                                .padding(.horizontal, 6)
                                .padding(.vertical, 2)
                                .background(Capsule().fill(Color.gray.opacity(0.15)))
                                .foregroundStyle(.secondary)
                        }
                    }
                    .buttonStyle(.plain)
                }
            } header: {
                Text("Up Next — \(service.playlist.count) item\(service.playlist.count == 1 ? "" : "s")")
            }
        }
        .listStyle(.plain)
    }

    // MARK: - Helpers

    private func jumpTo(index: Int) {
        guard service.playlist.indices.contains(index) else { return }
        // advancing from (index - 1) via next() lands on target index without changing mode
        var guardCount = 0
        while service.currentIndex != index && guardCount < service.playlist.count {
            guardCount += 1
            try? service.next()
        }
    }

    private var progressFraction: CGFloat {
        guard service.duration > 0 else { return 0 }
        return CGFloat(min(1, max(0, service.position / service.duration)))
    }

    private var currentFilename: String {
        guard let idx = service.currentIndex, service.playlist.indices.contains(idx) else {
            return "Nothing playing"
        }
        return service.playlist[idx].filename
    }

    private var currentItemIcon: String {
        guard let idx = service.currentIndex, service.playlist.indices.contains(idx) else {
            return "music.note.list"
        }
        return service.playlist[idx].kind == .video ? "play.tv.fill" : "music.note"
    }

    private var subtitleText: String {
        let mode = labelFor(service.mode)
        if let idx = service.currentIndex {
            return "\(idx + 1) of \(service.playlist.count) · \(mode)"
        }
        return mode
    }

    private func iconFor(_ mode: OpenRockyMediaPlaybackMode) -> String {
        switch mode {
        case .sequential: "arrow.right"
        case .loop: "repeat"
        case .random: "shuffle"
        case .repeatOne: "repeat.1"
        }
    }

    private func labelFor(_ mode: OpenRockyMediaPlaybackMode) -> String {
        switch mode {
        case .sequential: "Sequential"
        case .loop: "Loop All"
        case .random: "Shuffle"
        case .repeatOne: "Repeat One"
        }
    }

    private static func formatTime(_ seconds: Double) -> String {
        guard seconds.isFinite, seconds >= 0 else { return "--:--" }
        let total = Int(seconds)
        let m = total / 60
        let s = total % 60
        return String(format: "%d:%02d", m, s)
    }
}
