import SwiftUI

enum LibraryFilter: Hashable {
    case library(String)
    case downloaded
}

@Observable
@MainActor
final class LibraryViewModel {
    var libraries: [Library] = []
    var items: [LibraryItem] = []
    var isLoading: Bool = false
    var errorMessage: String?
    var selection: LibraryFilter?

    func loadLibraries(client: ABSClient) async {
        isLoading = true
        defer { isLoading = false }
        do {
            libraries = try await client.fetchLibraries()
            if selection == nil, let first = libraries.first {
                selection = .library(first.id)
            }
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    func loadItems(client: ABSClient, downloads: DownloadManager) async {
        guard let selection else { return }
        isLoading = true
        defer { isLoading = false }
        switch selection {
        case .library(let id):
            do {
                items = try await client.fetchItems(libraryId: id)
                errorMessage = nil
            } catch {
                errorMessage = error.localizedDescription
            }
        case .downloaded:
            items = downloads.downloadedItems.values.map { di in
                let files: [AudioFile] = di.tracks.enumerated().map { idx, t in
                    AudioFile(
                        ino: t.ino,
                        filename: t.filename,
                        ext: "",
                        durationSeconds: t.durationSeconds,
                        index: idx
                    )
                }
                var li = LibraryItem(
                    id: di.itemId,
                    title: di.title,
                    author: di.author,
                    durationSeconds: di.durationSeconds,
                    audioFiles: files
                )
                if let episodeId = di.episodeId {
                    li.mediaType = "podcast"
                    li.episodeId = episodeId
                }
                return li
            }.sorted { $0.title.localizedCaseInsensitiveCompare($1.title) == .orderedAscending }
            errorMessage = nil
        }
    }
}

struct MainView: View {
    @Environment(AppState.self) private var app
    @State private var vm = LibraryViewModel()
    @State private var navPath: [LibraryItem] = []
    @AppStorage("libraryLayout") private var layoutRaw: String = LibraryLayout.grid.rawValue
    #if os(iOS)
    @State private var showSettings: Bool = false
    #endif

    private var layout: LibraryLayout {
        LibraryLayout(rawValue: layoutRaw) ?? .grid
    }

    var body: some View {
        // Modifiers like .task and .onChange cannot chain after a #if/#endif block
        // in a @ViewBuilder — wrap the conditional nav in a separate property instead.
        navigationRoot
            .task { await loadAll() }
            .onChange(of: vm.selection) { _, _ in
                navPath.removeAll()
                Task { await loadAll() }
            }
            .safeAreaInset(edge: .bottom, spacing: 0) {
                PlayerBar()
                    .animation(.easeInOut(duration: 0.2), value: app.currentItem?.id)
                    .animation(.easeInOut(duration: 0.2), value: app.isPreparingPlayback)
            }
    }

    @ViewBuilder
    private var navigationRoot: some View {
        #if os(iOS)
        NavigationStack(path: $navPath) {
            detail
                .navigationTitle("")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .topBarLeading) {
                        libraryMenu
                    }
                    ToolbarItem(placement: .topBarTrailing) {
                        Menu {
                            Picker("Ansicht", selection: $layoutRaw) {
                                ForEach(LibraryLayout.allCases) { l in
                                    Label(l.label, systemImage: l.systemImage).tag(l.rawValue)
                                }
                            }
                            Divider()
                            Button {
                                showSettings = true
                            } label: {
                                Label("Einstellungen", systemImage: "gearshape")
                            }
                            Divider()
                            statusMenuSection
                        } label: {
                            Image(systemName: "ellipsis.circle")
                        }
                    }
                }
                .navigationDestination(for: LibraryItem.self) { podcast in
                    PodcastDetailView(podcast: podcast)
                }
        }
        .sheet(isPresented: $showSettings) {
            SettingsView()
                .environment(app)
        }
        #else
        NavigationSplitView {
            sidebar
        } detail: {
            NavigationStack(path: $navPath) {
                detail
                    .navigationDestination(for: LibraryItem.self) { podcast in
                        PodcastDetailView(podcast: podcast)
                    }
            }
        }
        #endif
    }

    private func loadAll() async {
        await vm.loadLibraries(client: app.client)
        await vm.loadItems(client: app.client, downloads: app.downloads)
        await app.refreshProgressCache()
    }

    private func handleSelect(_ item: LibraryItem) {
        if item.isPodcastContainer {
            navPath.append(item)
        } else {
            Task { await app.play(item: item) }
        }
    }

    // MARK: - macOS sidebar

    #if os(macOS)
    private var sidebar: some View {
        List(selection: $vm.selection) {
            Section("Bibliotheken") {
                ForEach(vm.libraries) { lib in
                    Label(lib.name, systemImage: "books.vertical")
                        .tag(LibraryFilter.library(lib.id))
                }
            }
            Section("Offline") {
                Label("Heruntergeladen", systemImage: "arrow.down.circle.fill")
                    .tag(LibraryFilter.downloaded)
            }
        }
        .listStyle(.sidebar)
        .navigationTitle("ABS Client")
        .safeAreaInset(edge: .bottom) {
            sidebarFooter
        }
    }

    private var sidebarFooter: some View {
        VStack(alignment: .leading, spacing: 6) {
            Divider()
            HStack(spacing: 8) {
                Circle()
                    .fill(app.network.isOnline ? .green : .orange)
                    .frame(width: 8, height: 8)
                Text(app.network.isOnline ? "Online" : "Offline")
                    .font(.caption)
                if app.sync.queuedCount > 0 {
                    Text("(\(app.sync.queuedCount) wartend)")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                Spacer()
            }
            HStack {
                Text(app.auth.username).font(.caption).foregroundStyle(.secondary)
                Spacer()
                Button("Abmelden") {
                    app.stopPlayback()
                    app.auth.logout()
                }
                .buttonStyle(.borderless)
                .font(.caption)
            }
        }
        .padding(.horizontal, 12)
        .padding(.vertical, 8)
    }
    #endif

    // MARK: - Detail content (shared)

    @ViewBuilder
    private var detail: some View {
        if vm.isLoading && vm.items.isEmpty {
            ProgressView("Lade Bibliothek …")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
        } else if let err = vm.errorMessage, vm.items.isEmpty {
            ContentUnavailableView("Fehler", systemImage: "exclamationmark.triangle", description: Text(err))
        } else if vm.items.isEmpty {
            ContentUnavailableView("Keine Hörbücher", systemImage: "books.vertical", description: Text("Diese Auswahl enthält noch keine Hörbücher."))
        } else {
            Group {
                switch layout {
                case .grid:
                    LibraryGridView(items: vm.items, onRefresh: loadAll) { handleSelect($0) }
                case .list:
                    LibraryListView(items: vm.items, onRefresh: loadAll) { handleSelect($0) }
                }
            }
            #if os(macOS)
            .navigationTitle(currentTitle)
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button {
                        Task { await loadAll() }
                    } label: {
                        if vm.isLoading {
                            ProgressView().controlSize(.small)
                        } else {
                            Image(systemName: "arrow.clockwise")
                        }
                    }
                    .help("Bibliothek, Cover und Hörfortschritte neu laden")
                    .disabled(vm.isLoading)
                }
                ToolbarItem(placement: .primaryAction) {
                    Picker("Ansicht", selection: $layoutRaw) {
                        ForEach(LibraryLayout.allCases) { l in
                            Image(systemName: l.systemImage)
                                .help(l.label)
                                .tag(l.rawValue)
                        }
                    }
                    .pickerStyle(.segmented)
                    .help("Zwischen Kachel- und Listenansicht wechseln")
                }
            }
            #endif
        }
    }

    // MARK: - iOS-only helpers

    #if os(iOS)
    private var libraryMenu: some View {
        Menu {
            Picker("Bibliothek", selection: Binding(
                get: { vm.selection ?? .library("") },
                set: { vm.selection = $0 }
            )) {
                Section("Bibliotheken") {
                    ForEach(vm.libraries) { lib in
                        Label(lib.name, systemImage: "books.vertical")
                            .tag(LibraryFilter.library(lib.id))
                    }
                }
                Section("Offline") {
                    Label("Heruntergeladen", systemImage: "arrow.down.circle.fill")
                        .tag(LibraryFilter.downloaded)
                }
            }
        } label: {
            HStack(spacing: 4) {
                Image(systemName: selectionIcon)
                Text(currentTitle)
                    .lineLimit(1)
                    .font(.headline)
                Image(systemName: "chevron.down")
                    .font(.caption)
            }
            .foregroundStyle(.primary)
        }
    }

    @ViewBuilder
    private var statusMenuSection: some View {
        Section(app.auth.username.isEmpty ? "Status" : "Angemeldet als \(app.auth.username)") {
            Label(app.network.isOnline ? "Online" : "Offline",
                  systemImage: app.network.isOnline ? "wifi" : "wifi.slash")
            if app.sync.queuedCount > 0 {
                Label("\(app.sync.queuedCount) Synchronisationen wartend",
                      systemImage: "arrow.triangle.2.circlepath")
            }
        }
    }

    private var selectionIcon: String {
        switch vm.selection {
        case .downloaded: return "arrow.down.circle.fill"
        default: return "books.vertical"
        }
    }
    #endif

    // MARK: - Shared helpers

    private var currentTitle: String {
        switch vm.selection {
        case .library(let id):
            return vm.libraries.first(where: { $0.id == id })?.name ?? "Bibliothek"
        case .downloaded:
            return "Heruntergeladen"
        case .none:
            return "Bibliothek"
        }
    }
}
