import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
    var library: LibraryViewModel
    var player: PlayerViewModel
    var scanner: ScannerService
    var playlist: PlaylistViewModel
    var shazam: ShazamService
    var db: DatabaseService
    @Binding var showNewPlaylistAlert: Bool
    var networkStatus: NetworkStatus?
    @State private var showRenameAlert = false
    @State private var showEditQueryAlert = false
    @State private var playlistNameInput = ""
    @State private var editQueryInput = ""
    @State private var itemToRename: (any PlaylistRepresentable)?
    @State private var smartPlaylistToEdit: SmartPlaylist?
    @State private var scrollToPlayingTrigger = UUID()
    @State private var searchText = ""
    @State private var keyMonitor: Any?
    @State private var showHome = false
    @State private var recentTracks: [Track] = []
    @State private var totalDuration: Double = 0
    @State private var monthlyAdditions: [MonthlyCount] = []

    var body: some View {
        VStack(spacing: 0) {
            if let status = networkStatus {
                switch status.mode {
                case .remote(let hostName):
                    HStack(spacing: 8) {
                        Image(systemName: "antenna.radiowaves.left.and.right")
                            .font(.system(size: 10)).foregroundStyle(.blue)
                        Text("Connected to \(hostName)")
                            .font(.system(size: 11, weight: .medium)).foregroundStyle(.blue)
                        Spacer()
                        Button("Refresh") { status.onRefreshLibrary?() }
                            .font(.system(size: 11)).buttonStyle(.plain).foregroundStyle(.secondary)
                        Button("Disconnect") { status.onDisconnect?() }
                            .font(.system(size: 11)).buttonStyle(.plain).foregroundStyle(.red)
                    }
                    .padding(.horizontal, 12).padding(.vertical, 4)
                    .background(Color.blue.opacity(0.08))
                case .hosting(let remoteName):
                    HStack(spacing: 8) {
                        Image(systemName: "antenna.radiowaves.left.and.right")
                            .font(.system(size: 10)).foregroundStyle(.green)
                        Text(remoteName != nil ? "Hosting · \(remoteName!) connected" : "Hosting")
                            .font(.system(size: 11, weight: .medium)).foregroundStyle(.green)
                        Spacer()
                    }
                    .padding(.horizontal, 12).padding(.vertical, 4)
                    .background(Color.green.opacity(0.08))
                }
            }

            SearchBarView(
                searchText: $searchText,
                trackCount: playlist.selectedItem != nil ? playlist.playlistTracks.count : library.trackCount,
                onSearch: { text in
                    if !text.isEmpty {
                        showHome = false
                    }
                    if !text.isEmpty && library.searchText.isEmpty {
                        library.sortColumn = "album"
                        library.sortAscending = true
                    }
                    library.search(text)
                    if playlist.selectedPlaylist != nil {
                        playlist.search(text)
                    }
                },
                onSaveSearch: { query in
                    try? playlist.createSmartPlaylist(searchQuery: query)
                },
                isShazamListening: shazam.isListening,
                onShazam: { shazam.isListening ? shazam.stopListening() : shazam.startListening() }
            )

            if scanner.isScanning {
                HStack(spacing: 8) {
                    ProgressView()
                        .controlSize(.small)
                    Text("Scanning... \(scanner.scanProgress.current) / \(scanner.scanProgress.total) tracks")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                .padding(.vertical, 4)
            }

            VStack(spacing: 0) {
                if showHome || playlist.selectedItem != nil {
                    HStack(spacing: 4) {
                        Button(action: {
                            playlist.deselectPlaylist()
                            searchText = ""
                            showHome = false
                        }) {
                            HStack(spacing: 2) {
                                Image(systemName: "chevron.left")
                                    .font(.system(size: 10))
                                Text("Library")
                                    .font(.system(size: 12))
                            }
                            .foregroundStyle(.secondary)
                        }
                        .buttonStyle(.plain)

                        Text("/")
                            .font(.system(size: 12))
                            .foregroundStyle(.quaternary)

                        Text(showHome ? "Home" : (playlist.selectedItem?.name ?? ""))
                            .font(.system(size: 12, weight: .medium))
                    }
                    .padding(.horizontal, 12)
                    .padding(.vertical, 4)
                    .frame(maxWidth: .infinity, alignment: .leading)
                }

                if showHome && playlist.selectedItem == nil {
                    HomeView(
                        recentTracks: recentTracks,
                        trackCount: library.trackCount,
                        totalDuration: totalDuration,
                        monthlyAdditions: monthlyAdditions,
                        onTrackDoubleClick: { track in
                            player.setQueue(recentTracks)
                            player.play(track)
                        },
                        onShowAll: {
                            showHome = false
                        }
                    )
                    .onAppear { loadHomeData() }
                } else {
                    TrackTableView(
                        tracks: playlist.selectedItem != nil ? playlist.playlistTracks : library.tracks,
                        playingTrackId: player.currentTrack?.id,
                        sortColumn: playlist.selectedSmartPlaylist != nil ? playlist.sortColumn : library.sortColumn,
                        sortAscending: playlist.selectedSmartPlaylist != nil ? playlist.sortAscending : library.sortAscending,
                        onSort: { column in
                            if playlist.selectedSmartPlaylist != nil {
                                playlist.sort(by: column)
                            } else if playlist.selectedItem == nil {
                                library.sort(by: column)
                            }
                        },
                        onDoubleClick: { track in
                            let trackList = playlist.selectedItem != nil ? playlist.playlistTracks : library.tracks
                            player.setQueue(trackList)
                            player.play(track)
                        },
                        playlists: playlist.playlists,
                        lastUsedPlaylistName: playlist.lastUsedPlaylistName,
                        selectedPlaylist: playlist.selectedPlaylist,
                        onAddToPlaylist: { track, targetPlaylist in
                            try? playlist.addTrack(track, to: targetPlaylist)
                        },
                        onAddToLastPlaylist: { track in
                            try? playlist.addTrackToLastUsedPlaylist(track)
                        },
                        onRemoveFromPlaylist: playlist.selectedPlaylist != nil ? { track in
                            if let selected = playlist.selectedPlaylist {
                                try? playlist.removeTrack(track, from: selected)
                            }
                        } : nil,
                        onReorder: playlist.selectedPlaylist != nil ? { from, to in
                            if let selected = playlist.selectedPlaylist {
                                try? playlist.moveTrack(in: selected, from: from, to: to)
                            }
                        } : nil,
                        scrollToPlayingTrigger: scrollToPlayingTrigger
                    )
                }
            }
            .frame(maxHeight: .infinity)

            PlaylistBarView(
                playlists: playlist.allPlaylists,
                selectedItem: showHome ? nil : playlist.selectedItem,
                isHomeSelected: showHome,
                isRemoteMode: networkStatus?.isRemoteMode ?? false,
                onHomeSelect: {
                    if showHome {
                        showHome = false
                    } else {
                        playlist.deselectPlaylist()
                        searchText = ""
                        showHome = true
                    }
                },
                onSelect: { item in
                    showHome = false
                    if item is SmartPlaylist {
                        playlist.sortColumn = "album"
                        playlist.sortAscending = true
                    }
                    playlist.selectItem(item)
                    if let smart = item as? SmartPlaylist {
                        searchText = smart.searchQuery
                        library.search(smart.searchQuery)
                    }
                },
                onDeselect: {
                    playlist.deselectPlaylist()
                    searchText = ""
                },
                onRename: { item in
                    itemToRename = item
                    playlistNameInput = item.name
                    showRenameAlert = true
                },
                onDelete: { item in
                    if let p = item as? Playlist {
                        try? playlist.deletePlaylist(p)
                    } else if let sp = item as? SmartPlaylist {
                        try? playlist.deleteSmartPlaylist(sp)
                    }
                },
                onEditQuery: { smart in
                    smartPlaylistToEdit = smart
                    editQueryInput = smart.searchQuery
                    showEditQueryAlert = true
                }
            )

            playerControls
        }
        .onAppear { installKeyboardMonitor() }
        .onDisappear { removeKeyboardMonitor() }
        .onDrop(of: [.fileURL], isTargeted: nil) { providers in
            handleDrop(providers)
            return true
        }
        .onChange(of: library.trackCount) { _, _ in
            if showHome { loadHomeData() }
        }
        .alert("New Playlist", isPresented: $showNewPlaylistAlert) {
            TextField("Playlist name", text: $playlistNameInput)
            Button("Cancel", role: .cancel) { playlistNameInput = "" }
            Button("Create") {
                let name = playlistNameInput.trimmingCharacters(in: .whitespaces)
                if !name.isEmpty {
                    try? playlist.createPlaylist(name: name)
                }
                playlistNameInput = ""
            }
        }
        .alert("Rename", isPresented: $showRenameAlert) {
            TextField("Name", text: $playlistNameInput)
            Button("Cancel", role: .cancel) { playlistNameInput = "" }
            Button("Rename") {
                let name = playlistNameInput.trimmingCharacters(in: .whitespaces)
                if !name.isEmpty, let item = itemToRename {
                    if let p = item as? Playlist {
                        try? playlist.renamePlaylist(p, to: name)
                    } else if let sp = item as? SmartPlaylist {
                        try? playlist.renameSmartPlaylist(sp, to: name)
                    }
                }
                playlistNameInput = ""
                itemToRename = nil
            }
        }
        .alert("Edit Search Query", isPresented: $showEditQueryAlert) {
            TextField("Search query", text: $editQueryInput)
            Button("Cancel", role: .cancel) { editQueryInput = "" }
            Button("Save") {
                let query = editQueryInput.trimmingCharacters(in: .whitespaces)
                if !query.isEmpty, let sp = smartPlaylistToEdit {
                    try? playlist.updateSmartPlaylistQuery(sp, to: query)
                    if playlist.selectedSmartPlaylist?.id == sp.id {
                        searchText = query
                        library.search(query)
                    }
                }
                editQueryInput = ""
                smartPlaylistToEdit = nil
            }
        }
        .alert("Song Identified", isPresented: Binding(
            get: { shazam.matchedTitle != nil },
            set: { if !$0 { shazam.clearResult() } }
        )) {
            Button("Search MP3") {
                let query = [shazam.matchedTitle, shazam.matchedArtist]
                    .compactMap { $0 }
                    .joined(separator: " ")
                NSPasteboard.general.clearContents()
                NSPasteboard.general.setString(query, forType: .string)
                if let url = URL(string: "https://freemp3music.org/") {
                    NSWorkspace.shared.open(url)
                }
                shazam.clearResult()
            }
            Button("Close", role: .cancel) { shazam.clearResult() }
        } message: {
            if let title = shazam.matchedTitle {
                Text("\(title) — \(shazam.matchedArtist ?? "Unknown Artist")")
            }
        }
        .alert("Shazam Error", isPresented: Binding(
            get: { shazam.errorMessage != nil },
            set: { if !$0 { shazam.clearResult() } }
        )) {
            Button("OK") { shazam.clearResult() }
        } message: {
            if let error = shazam.errorMessage {
                Text(error)
            }
        }
    }

    private var playerControls: some View {
        PlayerControlsView(
            currentTrack: player.currentTrack,
            isPlaying: player.isPlaying,
            currentTime: player.currentTime,
            duration: player.duration,
            volume: player.volume,
            isShuffled: player.isShuffled,
            onPlayPause: {
                if player.currentTrack == nil {
                    let trackList = playlist.selectedItem != nil ? playlist.playlistTracks : library.tracks
                    if let first = trackList.first {
                        player.setQueue(trackList)
                        player.play(first)
                    }
                } else {
                    player.togglePlayPause()
                }
            },
            onNext: { player.next() },
            onPrevious: { player.previous() },
            onSeek: { player.seek(to: $0) },
            onScrubStart: { player.beginScrubbing() },
            onScrub: { player.scrub(to: $0) },
            onScrubEnd: { player.endScrubbing(at: $0) },
            onVolumeChange: { player.setVolume($0) },
            onShuffleToggle: { player.toggleShuffle() },
            onNowPlayingTap: { scrollToPlayingTrigger = UUID() }
        )
    }

    private func installKeyboardMonitor() {
        keyMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [player, library, playlist] event in
            guard event.modifierFlags.intersection([.command, .control, .option, .shift]).isEmpty else {
                return event
            }
            guard let responder = NSApp.keyWindow?.firstResponder,
                  !(responder is NSTextView) else {
                return event
            }
            switch event.keyCode {
            case 49: // space
                if player.currentTrack == nil {
                    let trackList = playlist.selectedItem != nil ? playlist.playlistTracks : library.tracks
                    if let first = trackList.first {
                        player.setQueue(trackList)
                        player.play(first)
                    }
                } else {
                    player.togglePlayPause()
                }
                return nil
            case 123: // left arrow
                player.previous()
                return nil
            case 124: // right arrow
                player.next()
                return nil
            default:
                return event
            }
        }
    }

    private func removeKeyboardMonitor() {
        if let monitor = keyMonitor {
            NSEvent.removeMonitor(monitor)
            keyMonitor = nil
        }
    }

    private func loadHomeData() {
        recentTracks = (try? db.fetchRecentlyAdded(limit: 50)) ?? []
        totalDuration = (try? db.totalDuration()) ?? 0
        monthlyAdditions = (try? db.fetchMonthlyAdditions(months: 12)) ?? []
    }

    private func handleDrop(_ providers: [NSItemProvider]) {
        for provider in providers {
            provider.loadItem(forTypeIdentifier: "public.file-url") { data, _ in
                guard let data = data as? Data,
                      let url = URL(dataRepresentation: data, relativeTo: nil) else { return }

                var isDir: ObjCBool = false
                FileManager.default.fileExists(atPath: url.path, isDirectory: &isDir)

                Task {
                    if isDir.boolValue {
                        await scanner.scanFolder(url)
                    } else if ScannerService.audioExtensions.contains(url.pathExtension.lowercased()) {
                        if var track = await ScannerService.extractMetadata(from: url) {
                            try? scanner.db.insert(&track)
                        }
                    }
                }
            }
        }
    }
}
