import SwiftUI
import CoreData
import UIKit

struct QuickUpdateView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.managedObjectContext) private var context
    @Environment(\.scenePhase) private var scenePhase
    @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?

    // Clipboard round-trip: copy a value in your bank app, come back, one tap fills
    // the next pending source and the focus advances — no retyping, no memorizing.
    @FocusState private var focusedSource: NSManagedObjectID?
    @State private var clipboardAmount: Decimal?
    @State private var lastSuggestedRaw: String?

    /// First source (list order) still without a value — the "active" one.
    private var nextEmptySource: InvestmentSource? {
        sources.first { source in
            (values[source.objectID] ?? "").trimmingCharacters(in: .whitespaces).isEmpty
        }
    }

    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 {
                        if let amount = clipboardAmount, let target = nextEmptySource {
                            Section {
                                Button {
                                    applyClipboard(amount, to: target)
                                } label: {
                                    HStack(spacing: 8) {
                                        Image(systemName: "doc.on.clipboard.fill")
                                        Text(String(
                                            format: String(localized: "quick_update_paste_suggestion"),
                                            amount.currencyString, target.name
                                        ))
                                        .multilineTextAlignment(.leading)
                                        Spacer()
                                        Image(systemName: "arrow.down.circle.fill")
                                    }
                                    .font(.subheadline.weight(.semibold))
                                    .foregroundColor(.white)
                                    .padding(.vertical, 2)
                                }
                                .listRowBackground(Color.appPrimary)
                            }
                        }

                        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()
                checkClipboard()
            }
            .onChange(of: scenePhase) { _, phase in
                if phase == .active { checkClipboard() }
            }
        }
    }

    @ViewBuilder
    private func sourceRow(_ source: InvestmentSource) -> some View {
        VStack(spacing: 6) {
            HStack {
                VStack(alignment: .leading, spacing: 2) {
                    HStack(spacing: 6) {
                        Text(source.name)
                            .font(.subheadline.weight(.medium))
                        if source.objectID == nextEmptySource?.objectID {
                            Text(String(localized: "quick_update_next_badge"))
                                .font(.caption2.weight(.bold))
                                .padding(.horizontal, 6)
                                .padding(.vertical, 1)
                                .background(Color.appSecondary.opacity(0.15))
                                .foregroundColor(.appSecondary)
                                .clipShape(Capsule())
                        }
                    }
                    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)
                .focused($focusedSource, equals: source.objectID)
            }

            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 }
        )
    }

    /// Reads the pasteboard and offers the parsed amount for the next pending source.
    /// Skips values already suggested (or already typed) so returning to the app
    /// with the same clipboard doesn't nag.
    private func checkClipboard() {
        guard let raw = UIPasteboard.general.string, raw != lastSuggestedRaw,
              let parsed = CurrencyFormatter.parseUserInput(raw), parsed > 0,
              nextEmptySource != nil else {
            return
        }
        lastSuggestedRaw = raw
        clipboardAmount = parsed
    }

    private func applyClipboard(_ amount: Decimal, to source: InvestmentSource) {
        values[source.objectID] = String(format: "%.2f", NSDecimalNumber(decimal: amount).doubleValue)
        clipboardAmount = nil
        // Advance focus to the next source still pending, so the user can keep going
        // (type directly or hop to the next bank app and come back).
        if let next = nextEmptySource {
            focusedSource = next.objectID
        }
    }

    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)
            }
            // Keep the share-extension mirror in sync with what was just saved
            SharedQuickUpdateSync.refreshMirror()
            dismiss()
        } catch {
            saveError = error.localizedDescription
        }
        isSaving = false
    }
}
