import IndieSync
import SwiftData
import SwiftUI

/// The main list: a "Right here, right now" shelf of context-relevant notes
/// on top, then everything else newest-first. Search lives in its own tab
/// (`SearchView`, the tab bar's trailing magnifier).
struct NotesListView: View {
    @Environment(SyncEngine.self) private var syncEngine
    @Environment(ContextService.self) private var contextService
    @Query(sort: \NoteEntity.createdAt, order: .reverse) private var notes: [NoteEntity]

    @State private var composing = false
    @State private var editingNote: NoteEntity?
    @State private var assigningNote: NoteEntity?

    @AppStorage(ProjectsNaming.storageKey) private var namingRaw = ProjectsNaming.projects.rawValue
    private var naming: ProjectsNaming { ProjectsNaming(rawValue: namingRaw) ?? .projects }

    var body: some View {
        NavigationStack {
            list
                .navigationTitle("Notes")
                .toolbar {
                    ToolbarItem(placement: .primaryAction) {
                        Button {
                            composing = true
                        } label: {
                            Label("New Note", systemImage: "square.and.pencil")
                        }
                        .keyboardShortcut("n", modifiers: .command)
                    }
                }
                .sheet(isPresented: $composing) {
                    NoteEditorView(mode: .create)
                }
                .sheet(item: $editingNote) { note in
                    NoteEditorView(mode: .edit(note))
                }
                .sheet(item: $assigningNote) { note in
                    AssignProjectSheet(note: note)
                }
        }
    }

    private var list: some View {
        List {
            if let error = syncEngine.lastSyncError {
                Section {
                    Label(error, systemImage: "exclamationmark.icloud")
                        .foregroundStyle(.red)
                        .font(.footnote)
                }
            }

            if !relevantNotes.isEmpty {
                Section("Right here, right now") {
                    ForEach(relevantNotes) { note in
                        row(note)
                    }
                }
            }

            Section("All notes") {
                ForEach(orderedNotes) { note in
                    row(note)
                }
            }
        }
        .overlay {
            if notes.isEmpty {
                ContentUnavailableView(
                    "No notes yet",
                    systemImage: "square.and.pencil",
                    description: Text("Jot something down — Notes remembers where and when, so it can resurface at the right moment.")
                )
            }
        }
    }

    /// In-flight notes (transcription still pending) float to the top;
    /// everything else stays newest-first.
    private var orderedNotes: [NoteEntity] {
        notes.filter(isInFlight) + notes.filter { !isInFlight($0) }
    }

    private func isInFlight(_ note: NoteEntity) -> Bool {
        note.audio?.transcriptionStatus == .pending
    }

    private func row(_ note: NoteEntity) -> some View {
        Button {
            editingNote = note
        } label: {
            NoteRowView(note: note)
                .frame(maxWidth: .infinity, alignment: .leading)
                .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
        .swipeActions(edge: .leading) {
            Button {
                assigningNote = note
            } label: {
                Label(naming.singular, systemImage: "folder")
            }
            .tint(.indigo)
        }
        .swipeActions(edge: .trailing) {
            Button(role: .destructive) {
                delete(note)
            } label: {
                Label("Delete", systemImage: "trash")
            }
        }
    }

    /// Top context matches — notes whose capture context resembles "here and
    /// now" strongly enough to earn the shelf.
    private var relevantNotes: [NoteEntity] {
        let query = RelevanceQuery(context: contextService)
        return notes
            .filter { $0.isLive }
            .map { (note: $0, score: Relevance.score(RelevanceSignals(entity: $0), query: query)) }
            .filter { $0.score >= Relevance.surfacingThreshold }
            .sorted { $0.score > $1.score }
            .prefix(5)
            .map(\.note)
    }

    private func delete(_ note: NoteEntity) {
        guard let id = ULID(string: note.id) else { return }
        Task {
            try? await syncEngine.deleteNote(id: id)
        }
    }
}
