import SwiftUI
import CoreData

struct QuickUpdateView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.managedObjectContext) private var context
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \InvestmentSource.name, ascending: true)],
        predicate: NSPredicate(format: "isActive == YES"),
        animation: .default
    ) private var sources: FetchedResults<InvestmentSource>

    @State private var values: [NSManagedObjectID: String] = [:]
    @State private var contributions: [NSManagedObjectID: String] = [:]
    @State private var isSaving = false
    @State private var saveError: String?

    var body: some View {
        NavigationStack {
            ZStack {
                AppBackground()

                if sources.isEmpty {
                    ContentUnavailableView(
                        String(localized: "quick_update_no_sources"),
                        systemImage: "list.bullet",
                        description: Text(String(localized: "quick_update_no_sources_body"))
                    )
                } else {
                    List {
                        Section {
                            ForEach(sources) { source in
                                sourceRow(source)
                            }
                        } header: {
                            Text(String(localized: "quick_update_section_header"))
                        } footer: {
                            Text(String(localized: "quick_update_section_footer"))
                        }
                    }
                    .scrollContentBackground(.hidden)
                }
            }
            .navigationTitle(String(localized: "quick_update_title"))
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button(String(localized: "cancel")) { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button(String(localized: "quick_update_save")) {
                        saveAll()
                    }
                    .disabled(isSaving || filledValues.isEmpty)
                    .fontWeight(.semibold)
                }
            }
            .alert("Error", isPresented: Binding(
                get: { saveError != nil },
                set: { if !$0 { saveError = nil } }
            )) {
                Button("OK", role: .cancel) { saveError = nil }
            } message: {
                Text(saveError ?? "")
            }
            .onAppear { prefillContributions() }
        }
    }

    @ViewBuilder
    private func sourceRow(_ source: InvestmentSource) -> some View {
        VStack(spacing: 6) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    Text(source.name)
                        .font(.subheadline.weight(.medium))
                    if source.latestValue != .zero {
                        Text(source.latestValue.currencyString)
                            .font(.caption)
                            .foregroundColor(.secondary)
                    }
                }
                Spacer()
                TextField(
                    String(localized: "quick_update_placeholder"),
                    text: valueBinding(for: source)
                )
                .keyboardType(.decimalPad)
                .multilineTextAlignment(.trailing)
                .frame(width: 120)
                .font(.subheadline)
            }

            if contributions[source.objectID] != nil {
                HStack {
                    Text(String(localized: "quick_update_contribution_label"))
                        .font(.caption)
                        .foregroundColor(.secondary)
                    Spacer()
                    TextField(
                        String(localized: "quick_update_contribution_placeholder"),
                        text: contributionBinding(for: source)
                    )
                    .keyboardType(.decimalPad)
                    .multilineTextAlignment(.trailing)
                    .frame(width: 120)
                    .font(.caption)
                    .foregroundColor(.secondary)
                }
            }
        }
    }

    private var filledValues: [NSManagedObjectID: String] {
        values.filter { !$0.value.trimmingCharacters(in: .whitespaces).isEmpty }
    }

    private func valueBinding(for source: InvestmentSource) -> Binding<String> {
        Binding(
            get: { values[source.objectID] ?? "" },
            set: { values[source.objectID] = $0 }
        )
    }

    private func contributionBinding(for source: InvestmentSource) -> Binding<String> {
        Binding(
            get: { contributions[source.objectID] ?? "" },
            set: { contributions[source.objectID] = $0 }
        )
    }

    private func prefillContributions() {
        for source in sources {
            if let amount = MonthlyContributionStore.contribution(for: source.id) {
                contributions[source.objectID] = String(format: "%.2f", NSDecimalNumber(decimal: amount).doubleValue)
            }
        }
    }

    private func saveAll() {
        isSaving = true
        let now = Date()

        for source in sources {
            guard let raw = values[source.objectID],
                  !raw.trimmingCharacters(in: .whitespaces).isEmpty,
                  let value = CurrencyFormatter.parseUserInput(raw) else { continue }

            let snapshot = Snapshot(context: context)
            snapshot.id = UUID()
            snapshot.value = NSDecimalNumber(decimal: value)
            snapshot.date = now
            snapshot.source = source

            if let contribRaw = contributions[source.objectID],
               !contribRaw.trimmingCharacters(in: .whitespaces).isEmpty,
               let contrib = CurrencyFormatter.parseUserInput(contribRaw) {
                snapshot.contribution = NSDecimalNumber(decimal: contrib)
            }
        }

        do {
            try context.save()
            // Reschedule source reminders so they reflect the new snapshots
            for source in sources where values[source.objectID].map({ !$0.isEmpty }) == true {
                NotificationService.shared.scheduleReminder(for: source)
            }
            dismiss()
        } catch {
            saveError = error.localizedDescription
        }
        isSaving = false
    }
}
