import SwiftUI

/// The "Belege" tab root (see `App/MainTabView.swift`, which references this
/// type by a zero-arg init). Loads the signed-in user's receipts, supports
/// client-side search by merchant name, swipe-to-delete, and exporting the
/// currently visible receipts via `ExportSheet`. Owns its own
/// `NavigationStack`.
struct ReceiptsListView: View {
    @State private var receipts: [Receipt] = []
    @State private var searchText = ""
    @State private var isLoading = false
    @State private var loadErrorMessage: String?
    @State private var deleteErrorMessage: String?
    @State private var showExportSheet = false

    var body: some View {
        NavigationStack {
            Group {
                if receipts.isEmpty && !isLoading && loadErrorMessage == nil {
                    ContentUnavailableView(
                        "Noch keine Belege gescannt.",
                        systemImage: "list.bullet.rectangle"
                    )
                    .foregroundStyle(Color.zenithMuted)
                } else {
                    receiptsList
                }
            }
            .background(Color.zenithBg.ignoresSafeArea())
            .navigationTitle("Belege")
            .searchable(text: $searchText, prompt: "Suchen")
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        showExportSheet = true
                    } label: {
                        Label("Exportieren", systemImage: "square.and.arrow.up")
                    }
                    .disabled(filteredReceipts.isEmpty)
                }
            }
            .task {
                await load()
            }
            .refreshable {
                await load()
            }
            .sheet(isPresented: $showExportSheet) {
                ExportSheet(receipts: filteredReceipts)
            }
            .alert(
                "Löschen fehlgeschlagen",
                isPresented: Binding(
                    get: { deleteErrorMessage != nil },
                    set: { isPresented in
                        if !isPresented { deleteErrorMessage = nil }
                    }
                )
            ) {
                Button("OK", role: .cancel) { deleteErrorMessage = nil }
            } message: {
                Text(deleteErrorMessage ?? "")
            }
        }
    }

    /// Client-side filter by merchant name — this is also what gets exported
    /// via the toolbar button, so exporting after a search exports only the
    /// filtered set.
    private var filteredReceipts: [Receipt] {
        let trimmed = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty else { return receipts }
        return receipts.filter { $0.merchant.name.localizedCaseInsensitiveContains(trimmed) }
    }

    private var receiptsList: some View {
        List {
            if let loadErrorMessage {
                Section {
                    Text(loadErrorMessage)
                        .zenithBodySmStyle(color: .zenithError)
                }
                .listRowBackground(Color.zenithSurface)
                .listRowSeparatorTint(Color.zenithBorder)
            }

            ForEach(filteredReceipts) { receipt in
                NavigationLink {
                    ReceiptDetailView(receipt: receipt)
                } label: {
                    ReceiptRow(receipt: receipt)
                }
                .listRowBackground(Color.zenithSurface)
                .listRowSeparatorTint(Color.zenithBorder)
                .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                    Button(role: .destructive) {
                        Task { await delete(receipt) }
                    } label: {
                        Label("Löschen", systemImage: "trash")
                    }
                }
            }
        }
        .listStyle(.plain)
        .zenithListBackground()
    }

    private func load() async {
        isLoading = true
        loadErrorMessage = nil
        defer { isLoading = false }
        do {
            receipts = try await ReceiptsAPI.list()
        } catch {
            loadErrorMessage = error.localizedDescription
        }
    }

    /// Optimistic delete: removes the row immediately, then confirms with the
    /// server. On failure the row is reinserted at its original position and
    /// an error alert is shown.
    private func delete(_ receipt: Receipt) async {
        guard let index = receipts.firstIndex(where: { $0.id == receipt.id }) else { return }
        let removed = receipts.remove(at: index)
        do {
            try await ReceiptsAPI.delete(id: removed.id)
        } catch {
            receipts.insert(removed, at: min(index, receipts.count))
            deleteErrorMessage = error.localizedDescription
        }
    }
}
