import SwiftUI
import UserNotifications

struct GassiZeitenView: View {
    @State private var items: [GassiZeit] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var showAdd = false

    private let weekdayLabels: [String: String] = [
        "mo": "Mo", "di": "Di", "mi": "Mi", "do": "Do",
        "fr": "Fr", "sa": "Sa", "so": "So"
    ]
    private let weekdayOrder = ["mo", "di", "mi", "do", "fr", "sa", "so"]

    var body: some View {
        content
            .navigationTitle("Gassi-Zeiten")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button { showAdd = true } label: { Image(systemName: "plus") }
                }
            }
            .sheet(isPresented: $showAdd) {
                AddGassiZeitSheet { await load() }
            }
            .task {
                _ = try? await UNUserNotificationCenter.current()
                    .requestAuthorization(options: [.alert, .sound, .badge])
                await load()
            }
            .refreshable { await load() }
    }

    @ViewBuilder
    private var content: some View {
        if isLoading && items.isEmpty {
            ProgressView()
        } else if let errorMessage, items.isEmpty {
            ContentUnavailableView("Konnte nicht laden", systemImage: "wifi.slash", description: Text(errorMessage))
        } else if items.isEmpty {
            ContentUnavailableView(
                "Noch keine Gassi-Zeiten",
                systemImage: "alarm",
                description: Text("Tippe oben rechts auf +, um regelmäßige Erinnerungen zu setzen.")
            )
        } else {
            List {
                Section {
                    ForEach(items) { z in
                        row(z)
                    }
                } footer: {
                    Text("Erinnerungen kommen lokal vom iPhone — auch ohne Internet.")
                        .font(.caption2)
                        .foregroundStyle(.tertiary)
                }
            }
        }
    }

    private func row(_ z: GassiZeit) -> some View {
        HStack(spacing: 12) {
            Image(systemName: "alarm.fill")
                .foregroundStyle(z.aktiv == 0 ? Color.secondary : Color.accentColor)
                .frame(width: 28)
            VStack(alignment: .leading, spacing: 4) {
                HStack(spacing: 8) {
                    Text(z.uhrzeit).font(.headline.monospacedDigit())
                    Spacer()
                    if let dog = z.dogName {
                        Text(dog).font(.caption).foregroundStyle(.secondary)
                    }
                }
                HStack(spacing: 6) {
                    ForEach(weekdayOrder, id: \.self) { wd in
                        let active = z.wochentage.contains(wd)
                        Text(weekdayLabels[wd] ?? wd)
                            .font(.caption2.bold())
                            .foregroundStyle(active ? .white : .secondary)
                            .frame(width: 22, height: 22)
                            .background(active ? Color.accentColor : Color.secondary.opacity(0.15), in: Circle())
                    }
                }
                if let n = z.notiz, !n.isEmpty {
                    Text(n).font(.caption).foregroundStyle(.secondary)
                }
            }
        }
        .padding(.vertical, 4)
    }

    private func load() async {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }
        do {
            items = try await APIClient.shared.get("/api/gassi-zeiten?nur_eigene=true")
            // Re-sync local notifications to reflect server state.
            for z in items where z.isMine ?? true {
                await GassiZeitenScheduler.reschedule(z)
            }
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

private struct AddGassiZeitSheet: View {
    @Environment(\.dismiss) private var dismiss
    let onSaved: () async -> Void

    @State private var time = Calendar.current.date(bySettingHour: 8, minute: 0, second: 0, of: .now) ?? .now
    @State private var selectedDays: Set<String> = ["mo", "di", "mi", "do", "fr"]
    @State private var notiz = ""
    @State private var dogs: [Dog] = []
    @State private var dogId: Int?
    @State private var isSaving = false
    @State private var errorMessage: String?

    private let weekdayOrder = ["mo", "di", "mi", "do", "fr", "sa", "so"]
    private let weekdayLabels: [String: String] = [
        "mo": "Mo", "di": "Di", "mi": "Mi", "do": "Do",
        "fr": "Fr", "sa": "Sa", "so": "So"
    ]

    var body: some View {
        NavigationStack {
            Form {
                Section("Uhrzeit") {
                    DatePicker("Uhrzeit", selection: $time, displayedComponents: .hourAndMinute)
                        .environment(\.locale, Locale(identifier: "de_DE"))
                }
                Section("Wochentage") {
                    HStack(spacing: 8) {
                        ForEach(weekdayOrder, id: \.self) { wd in
                            let active = selectedDays.contains(wd)
                            Button {
                                if active { selectedDays.remove(wd) } else { selectedDays.insert(wd) }
                            } label: {
                                Text(weekdayLabels[wd] ?? wd)
                                    .font(.caption.bold())
                                    .foregroundStyle(active ? .white : .primary)
                                    .frame(width: 34, height: 34)
                                    .background(active ? Color.accentColor : Color.secondary.opacity(0.15), in: Circle())
                            }
                            .buttonStyle(.plain)
                        }
                    }
                }
                Section("Hund (optional)") {
                    Picker("Hund", selection: $dogId) {
                        Text("Ohne Hund").tag(Int?.none)
                        ForEach(dogs) { d in Text(d.name).tag(Int?.some(d.id)) }
                    }
                }
                Section("Notiz (optional)") {
                    TextField("Notiz", text: $notiz, axis: .vertical)
                        .lineLimit(2...4)
                }
                if let errorMessage {
                    Section { Text(errorMessage).font(.footnote).foregroundStyle(.red) }
                }
            }
            .navigationTitle("Neue Gassi-Zeit")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Abbrechen") { dismiss() }.disabled(isSaving)
                }
                ToolbarItem(placement: .confirmationAction) {
                    if isSaving { ProgressView() }
                    else { Button("Sichern") { Task { await save() } }.disabled(selectedDays.isEmpty) }
                }
            }
            .task { dogs = (try? await APIClient.shared.get("/api/dogs")) ?? [] }
        }
    }

    private func save() async {
        isSaving = true
        errorMessage = nil
        defer { isSaving = false }

        let f = DateFormatter()
        f.dateFormat = "HH:mm"
        let body = GassiZeitCreateBody(
            dogId: dogId,
            wochentage: weekdayOrder.filter { selectedDays.contains($0) },
            uhrzeit: f.string(from: time),
            ortName: nil,
            lat: nil,
            lon: nil,
            radiusM: 500,
            notiz: notiz.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? nil : notiz
        )
        do {
            let created: GassiZeit = try await APIClient.shared.post("/api/gassi-zeiten", body: body)
            await GassiZeitenScheduler.reschedule(created)
            await onSaved()
            dismiss()
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}
