import os
import SwiftData
import SwiftUI

private let cloudLogger = Logger(subsystem: "com.mixboard", category: "CloudAdd")

/// Browse cloud music from the Chad Music server.
/// Presented as a sheet — browse categories → albums → tracks, play or add to playlists.
struct CloudBrowserView: View {
    @Environment(PlayerViewModel.self) private var playerVM
    @EnvironmentObject private var theme: AppTheme
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) private var dismiss

    @State private var client = ChadMusicAPIClient.shared
    @State private var stats: ChadStats?
    @State private var isLoadingStats = false
    @State private var errorMessage: String?

    var body: some View {
        NavigationStack {
            Group {
                if !client.isConfigured {
                    notConfiguredView
                } else {
                    categoryListView
                }
            }
            .navigationTitle("Cloud Music")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Done") { dismiss() }
                }
            }
        }
    }

    // MARK: - Not Configured

    private var notConfiguredView: some View {
        VStack(spacing: 20) {
            Spacer()
            Image(systemName: "cloud.slash")
                .font(.system(size: 50))
                .foregroundStyle(theme.tertiaryText)
            Text("Not Connected")
                .font(.title2)
                .foregroundStyle(theme.secondaryText)
            Text("Set up your Chad Music server in Settings to browse cloud music.")
                .font(.subheadline)
                .foregroundStyle(theme.tertiaryText)
                .multilineTextAlignment(.center)
                .padding(.horizontal, 40)
            Spacer()
        }
    }

    // MARK: - Category List

    private var categoryListView: some View {
        List {
            if let stats {
                Section {
                    HStack(spacing: 16) {
                        statBadge(value: stats.tracks, label: "Tracks")
                        statBadge(value: stats.albums, label: "Albums")
                        statBadge(value: stats.artists, label: "Artists")
                    }
                    .frame(maxWidth: .infinity)
                    .listRowBackground(Color.clear)
                }
            }

            Section("Browse") {
                ForEach(ChadCategoryType.allCases) { category in
                    NavigationLink {
                        if category == .album {
                            AlbumListView()
                        } else {
                            CategoryDetailView(category: category)
                        }
                    } label: {
                        Label(category.displayName, systemImage: category.icon)
                    }
                }
            }
        }
        .listStyle(.insetGrouped)
        .task {
            await loadStats()
        }
        .refreshable {
            await loadStats()
        }
    }

    private func statBadge(value: Int?, label: String) -> some View {
        VStack(spacing: 2) {
            Text("\(value ?? 0)")
                .font(.system(size: 20, weight: .bold, design: .rounded))
                .foregroundStyle(theme.accent)
            Text(label)
                .font(.caption2)
                .foregroundStyle(theme.secondaryText)
        }
        .frame(maxWidth: .infinity)
    }

    private func loadStats() async {
        isLoadingStats = true
        errorMessage = nil
        let result = await client.testConnection()
        switch result {
        case .success(let s):
            stats = s
        case .failure(let error):
            errorMessage = error.localizedDescription
        }
        isLoadingStats = false
    }
}

// MARK: - Album List View

struct AlbumListView: View {
    @Environment(PlayerViewModel.self) private var playerVM
    @EnvironmentObject private var theme: AppTheme
    @Environment(\.modelContext) private var modelContext

    @State private var albums: [ChadAlbum] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var searchText = ""

    private var filteredAlbums: [ChadAlbum] {
        if searchText.isEmpty { return albums }
        let query = searchText.lowercased()
        return albums.filter {
            ($0.title.lowercased().contains(query)) ||
            ($0.artist?.lowercased().contains(query) ?? false)
        }
    }

    var body: some View {
        Group {
            if isLoading && albums.isEmpty {
                ProgressView("Loading albums…")
            } else if let error = errorMessage, albums.isEmpty {
                Text(error).foregroundStyle(.red)
            } else {
                List(filteredAlbums) { album in
                    NavigationLink {
                        AlbumDetailView(album: album)
                    } label: {
                        AlbumRow(album: album)
                    }
                }
                .listStyle(.plain)
                .searchable(text: $searchText, prompt: "Search albums")
            }
        }
        .navigationTitle("Albums")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await loadAlbums()
        }
    }

    private func loadAlbums() async {
        isLoading = true
        do {
            albums = try await ChadMusicAPIClient.shared.fetchAlbums()
        } catch {
            errorMessage = error.localizedDescription
        }
        isLoading = false
    }
}

// MARK: - Album Row

struct AlbumRow: View {
    let album: ChadAlbum
    @EnvironmentObject private var theme: AppTheme

    var body: some View {
        HStack(spacing: 12) {
            Image(systemName: "opticaldisc")
                .font(.title2)
                .foregroundStyle(theme.accent)
                .frame(width: 44, height: 44)
                .background(theme.accent.opacity(0.1))
                .clipShape(RoundedRectangle(cornerRadius: 8))

            VStack(alignment: .leading, spacing: 2) {
                Text(album.title)
                    .font(.subheadline.weight(.medium))
                    .foregroundStyle(theme.primaryText)
                    .lineLimit(1)
                HStack(spacing: 4) {
                    if let artist = album.artist {
                        Text(artist)
                            .font(.caption)
                            .foregroundStyle(theme.secondaryText)
                            .lineLimit(1)
                    }
                    if let year = album.year {
                        Text("·")
                            .foregroundStyle(theme.tertiaryText)
                        Text("\(year)")
                            .font(.caption)
                            .foregroundStyle(theme.tertiaryText)
                    }
                }
            }

            Spacer()

            if let count = album.trackCount {
                Text("\(count)")
                    .font(.caption)
                    .foregroundStyle(theme.tertiaryText)
            }
        }
    }
}

// MARK: - Category Detail View

struct CategoryDetailView: View {
    let category: ChadCategoryType
    @EnvironmentObject private var theme: AppTheme

    @State private var items: [ChadCategory] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var searchText = ""

    private var filteredItems: [ChadCategory] {
        if searchText.isEmpty { return items }
        let query = searchText.lowercased()
        return items.filter { $0.name.lowercased().contains(query) }
    }

    var body: some View {
        Group {
            if isLoading && items.isEmpty {
                ProgressView("Loading…")
            } else if let error = errorMessage, items.isEmpty {
                Text(error).foregroundStyle(.red)
            } else {
                List(filteredItems) { item in
                    HStack {
                        Text(item.name)
                            .foregroundStyle(theme.primaryText)
                        Spacer()
                        if let count = item.count {
                            Text("\(count)")
                                .font(.caption)
                                .foregroundStyle(theme.tertiaryText)
                        }
                    }
                }
                .listStyle(.plain)
                .searchable(text: $searchText, prompt: "Search \(category.displayName.lowercased())")
            }
        }
        .navigationTitle(category.displayName)
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await load()
        }
    }

    private func load() async {
        isLoading = true
        do {
            items = try await ChadMusicAPIClient.shared.fetchCategory(category)
        } catch {
            errorMessage = error.localizedDescription
        }
        isLoading = false
    }
}

// MARK: - Album Detail View

struct AlbumDetailView: View {
    let album: ChadAlbum
    @Environment(PlayerViewModel.self) private var playerVM
    @EnvironmentObject private var theme: AppTheme
    @Environment(\.modelContext) private var modelContext

    @AppStorage("trackTapAction") private var trackTapAction = "playNow"

    @State private var tracks: [ChadTrack] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var showAddToPlaylist = false
    @State private var tracksToAdd: [ChadTrack] = []

    @Query(sort: \Playlist.dateModified, order: .reverse) private var playlists: [Playlist]

    var body: some View {
        Group {
            if isLoading && tracks.isEmpty {
                ProgressView("Loading tracks…")
            } else if let error = errorMessage, tracks.isEmpty {
                Text(error).foregroundStyle(.red)
            } else {
                List {
                    // Album header
                    Section {
                        VStack(spacing: 8) {
                            Image(systemName: "opticaldisc.fill")
                                .font(.system(size: 50))
                                .foregroundStyle(theme.accent)
                            Text(album.title)
                                .font(.title3.bold())
                                .foregroundStyle(theme.primaryText)
                                .multilineTextAlignment(.center)
                            if let artist = album.artist {
                                Text(artist)
                                    .font(.subheadline)
                                    .foregroundStyle(theme.secondaryText)
                            }
                            HStack(spacing: 12) {
                                if let year = album.year {
                                    Text("\(year)")
                                }
                                if let genre = album.genre {
                                    Text(genre)
                                }
                                Text("\(tracks.count) tracks")
                            }
                            .font(.caption)
                            .foregroundStyle(theme.tertiaryText)
                        }
                        .frame(maxWidth: .infinity)
                        .listRowBackground(Color.clear)
                    }

                    // Play all / Add all
                    Section {
                        Button {
                            playAll()
                        } label: {
                            Label("Play All", systemImage: "play.fill")
                        }

                        Button {
                            tracksToAdd = tracks
                            showAddToPlaylist = true
                        } label: {
                            Label("Add All to Playlist", systemImage: "plus.circle")
                        }
                    }

                    // Track list
                    Section {
                        ForEach(Array(tracks.enumerated()), id: \.element.id) { index, track in
                            CloudTrackRow(track: track, index: index + 1) {
                                if trackTapAction == "addToQueue" {
                                    playerVM.addToQueue(QueueEntry.from(cloudTrack: track))
                                } else {
                                    playTrack(track)
                                }
                            }
                            .contextMenu {
                                Button {
                                    playTrack(track)
                                } label: {
                                    Label("Play Now", systemImage: "play.fill")
                                }
                                Button {
                                    playerVM.playNextInQueue(QueueEntry.from(cloudTrack: track))
                                } label: {
                                    Label("Play Next", systemImage: "text.insert")
                                }
                                Button {
                                    playerVM.addToQueue(QueueEntry.from(cloudTrack: track))
                                } label: {
                                    Label("Add to Queue", systemImage: "text.append")
                                }
                                Divider()
                                Button {
                                    tracksToAdd = [track]
                                    showAddToPlaylist = true
                                } label: {
                                    Label("Add to Playlist", systemImage: "plus.circle")
                                }
                            }
                        }
                    }
                }
                .listStyle(.insetGrouped)
            }
        }
        .navigationTitle(album.title)
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await loadTracks()
        }
        .sheet(isPresented: $showAddToPlaylist) {
            CloudAddToPlaylistSheet(
                tracksToAdd: $tracksToAdd,
                playlists: playlists
            )
        }
    }

    private func loadTracks() async {
        isLoading = true
        do {
            tracks = try await ChadMusicAPIClient.shared.fetchAlbumTracks(albumId: album.id)
        } catch {
            errorMessage = error.localizedDescription
        }
        isLoading = false
    }

    private func playTrack(_ track: ChadTrack) {
        let client = ChadMusicAPIClient.shared
        guard let url = client.streamURL(for: track.url) else { return }
        playerVM.loadAndPlayCloud(track, streamURL: url, authHeaders: client.authHeaders)
    }

    private func playAll() {
        guard let firstTrack = tracks.first else { return }
        playTrack(firstTrack)
    }
}

// MARK: - Cloud Track Row

struct CloudTrackRow: View {
    let track: ChadTrack
    let index: Int
    let onTap: () -> Void
    @Environment(PlayerViewModel.self) private var playerVM
    @EnvironmentObject private var theme: AppTheme

    private var isCurrentlyPlaying: Bool {
        playerVM.isCloudPlayback && playerVM.currentCloudTrack?.id == track.id
    }

    var body: some View {
        Button(action: onTap) {
            HStack(spacing: 12) {
                // Track number or playing indicator
                ZStack {
                    if isCurrentlyPlaying {
                        Image(systemName: playerVM.isPlaying ? "speaker.wave.2.fill" : "speaker.fill")
                            .font(.caption)
                            .foregroundStyle(theme.accent)
                    } else {
                        Text("\(track.trackNumber ?? index)")
                            .font(.caption.monospacedDigit())
                            .foregroundStyle(theme.tertiaryText)
                    }
                }
                .frame(width: 28)

                // Track info
                VStack(alignment: .leading, spacing: 1) {
                    Text(track.title)
                        .font(.subheadline)
                        .foregroundStyle(isCurrentlyPlaying ? theme.accent : theme.primaryText)
                        .lineLimit(1)
                    if let artist = track.artist, !artist.isEmpty {
                        Text(artist)
                            .font(.caption)
                            .foregroundStyle(theme.secondaryText)
                            .lineLimit(1)
                    }
                }

                Spacer()

                // Duration
                Text(track.formattedDuration)
                    .font(.caption.monospacedDigit())
                    .foregroundStyle(theme.tertiaryText)
            }
        }
        .buttonStyle(.plain)
    }
}

// MARK: - Cloud Add To Playlist Sheet

struct CloudAddToPlaylistSheet: View {
    @Binding var tracksToAdd: [ChadTrack]
    let playlists: [Playlist]
    @Environment(\.modelContext) private var modelContext
    @Environment(\.dismiss) private var dismiss
    @Environment(PlaylistViewModel.self) private var playlistVM
    @EnvironmentObject private var theme: AppTheme

    @State private var showNewPlaylistAlert = false
    @State private var newPlaylistName = ""

    var body: some View {
        NavigationStack {
            List {
                // New Playlist button
                Button {
                    newPlaylistName = ""
                    showNewPlaylistAlert = true
                } label: {
                    HStack {
                        Image(systemName: "plus.circle.fill")
                            .foregroundStyle(theme.accent)
                        Text("New Playlist")
                            .foregroundStyle(theme.accent)
                    }
                }

                // Existing playlists
                ForEach(playlists) { playlist in
                    Button {
                        addTracks(to: playlist)
                        dismiss()
                    } label: {
                        HStack {
                            Image(systemName: "music.note.list")
                                .foregroundStyle(theme.accent)
                            Text(playlist.name)
                                .foregroundStyle(theme.primaryText)
                            Spacer()
                            Text("\(playlist.entries.count) tracks")
                                .font(.caption)
                                .foregroundStyle(theme.tertiaryText)
                        }
                    }
                }
            }
            .navigationTitle("Add to Playlist")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Cancel") { dismiss() }
                }
            }
            .alert("New Playlist", isPresented: $showNewPlaylistAlert) {
                TextField("Playlist name", text: $newPlaylistName)
                Button("Create") {
                    guard !newPlaylistName.trimmingCharacters(in: .whitespaces).isEmpty else { return }
                    let playlist = Playlist(name: newPlaylistName.trimmingCharacters(in: .whitespaces))
                    modelContext.insert(playlist)
                    addTracks(to: playlist)
                    dismiss()
                }
                Button("Cancel", role: .cancel) {}
            } message: {
                Text("Enter a name for the new playlist.")
            }
        }
    }

    private func addTracks(to playlist: Playlist) {
        cloudLogger.notice("START — adding \(self.tracksToAdd.count) tracks to '\(playlist.name)' (current entries: \(playlist.entries.count))")

        var newTracks: [Track] = []
        for chadTrack in tracksToAdd {
            let track = Track.fromCloud(chadTrack)
            modelContext.insert(track)
            newTracks.append(track)
            cloudLogger.notice("inserted track '\(track.title)' isCloud=\(track.isCloud) cloudId=\(track.cloudTrackId ?? "nil")")
        }

        do {
            try modelContext.save()
            cloudLogger.notice("saved \(newTracks.count) tracks OK")
        } catch {
            cloudLogger.error("SAVE TRACKS FAILED: \(error)")
        }

        for track in newTracks {
            playlist.addTrack(track)
            cloudLogger.notice("added '\(track.title)' to playlist, entries now: \(playlist.entries.count)")
        }

        do {
            try modelContext.save()
            cloudLogger.notice("final save OK — playlist '\(playlist.name)' entries: \(playlist.entries.count)")
        } catch {
            cloudLogger.error("FINAL SAVE FAILED: \(error)")
        }

        for entry in playlist.entries {
            cloudLogger.notice("VERIFY entry pos=\(entry.position) track=\(entry.track?.title ?? "NIL")")
        }
    }
}
