import SwiftUI
import MapKit
import PhotosUI

struct VerloreneHundeView: View {
    @State private var location = OneShotLocation()
    @State private var lostDogs: [LostDog] = []
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var showReport = false
    @State private var cameraPosition: MapCameraPosition = .automatic
    @State private var tappedDog: LostDog?

    var body: some View {
        Group {
            if let coord = location.coordinate {
                content(at: coord)
            } else if location.error != nil {
                ContentUnavailableView(
                    "Kein Standort",
                    systemImage: "location.slash",
                    description: Text(location.error ?? "")
                )
            } else {
                ProgressView("Hole Standort…")
            }
        }
        .navigationTitle("Verlorene Hunde")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            if location.coordinate != nil {
                ToolbarItem(placement: .topBarTrailing) {
                    Button {
                        showReport = true
                    } label: {
                        Label("Melden", systemImage: "exclamationmark.bubble")
                    }
                }
            }
        }
        .sheet(isPresented: $showReport) {
            if let coord = location.coordinate {
                ReportLostDogSheet(coord: coord) { await load() }
            }
        }
        .sheet(item: $tappedDog) { dog in
            NavigationStack {
                LostDogDetailView(dog: dog)
                    .toolbar {
                        ToolbarItem(placement: .topBarTrailing) {
                            Button("Schließen") { tappedDog = nil }
                        }
                    }
            }
        }
        .task {
            location.request()
            await load()
        }
        .onChange(of: location.coordinate?.latitude) { _, _ in
            if let c = location.coordinate { centerOn(c) }
            Task { await load() }
        }
        .refreshable { await load() }
    }

    private func content(at coord: CLLocationCoordinate2D) -> some View {
        VStack(spacing: 0) {
            Map(position: $cameraPosition) {
                UserAnnotation()
                ForEach(lostDogs) { dog in
                    Annotation(dog.name,
                        coordinate: CLLocationCoordinate2D(latitude: dog.lat, longitude: dog.lon)
                    ) {
                        Button {
                            tappedDog = dog
                        } label: {
                            Image(systemName: "magnifyingglass.circle.fill")
                                .font(.title2)
                                .foregroundStyle(.white, Color.accentColor)
                                .background(.white, in: Circle())
                                .shadow(radius: 2)
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
            .frame(height: 260)
            .ignoresSafeArea(edges: .top)
            .onAppear { centerOn(coord) }
            .overlay(alignment: .topTrailing) {
                Button {
                    centerOn(coord)
                } label: {
                    Image(systemName: "location.fill")
                        .font(.callout.bold())
                        .foregroundStyle(Color.accentColor)
                        .padding(10)
                        .background(.thinMaterial, in: Circle())
                        .shadow(radius: 2)
                }
                .padding(.top, 60)
                .padding(.trailing, 12)
            }

            if isLoading && lostDogs.isEmpty {
                ProgressView().padding(.top, 30)
                Spacer()
            } else if let errorMessage, lostDogs.isEmpty {
                ContentUnavailableView(
                    "Konnte nicht laden",
                    systemImage: "wifi.slash",
                    description: Text(errorMessage)
                )
                .padding(.top, 30)
                Spacer()
            } else if lostDogs.isEmpty {
                ContentUnavailableView(
                    "Keine vermissten Hunde",
                    systemImage: "checkmark.circle",
                    description: Text("In 25 km Umkreis sind aktuell keine Vermisstmeldungen aktiv.")
                )
                .padding(.top, 30)
                Spacer()
            } else {
                List(lostDogs) { dog in
                    NavigationLink {
                        LostDogDetailView(dog: dog)
                    } label: {
                        LostDogRow(dog: dog)
                    }
                }
                .listStyle(.plain)
            }
        }
    }

    private func centerOn(_ coord: CLLocationCoordinate2D) {
        withAnimation(.easeInOut(duration: 0.4)) {
            cameraPosition = .region(MKCoordinateRegion(
                center: coord,
                span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
            ))
        }
    }

    private func load() async {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }
        do {
            var path = "/api/lost?radius_km=25"
            if let coord = location.coordinate {
                path = "/api/lost?lat=\(coord.latitude)&lon=\(coord.longitude)&radius_km=25"
            }
            lostDogs = try await APIClient.shared.get(path)
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

private struct LostDogRow: View {
    let dog: LostDog

    var body: some View {
        HStack(spacing: 12) {
            avatar
                .frame(width: 56, height: 56)
                .clipShape(RoundedRectangle(cornerRadius: 8))
            VStack(alignment: .leading, spacing: 2) {
                HStack {
                    Text(dog.name).font(.headline)
                    Spacer()
                    if let d = dog.distanzM {
                        Text(distLabel(d))
                            .font(.caption.monospacedDigit())
                            .foregroundStyle(.secondary)
                    }
                }
                if let r = dog.rasse, !r.isEmpty {
                    Text(r).font(.caption).foregroundStyle(.secondary)
                }
                Text(dog.beschreibung)
                    .font(.caption)
                    .foregroundStyle(.secondary)
                    .lineLimit(2)
            }
        }
        .padding(.vertical, 4)
    }

    @ViewBuilder
    private var avatar: some View {
        if let path = dog.fotoUrl,
           let url = URL(string: "https://banyaro.app\(path)") {
            AsyncImage(url: url) { phase in
                switch phase {
                case .success(let img): img.resizable().scaledToFill()
                default: placeholder
                }
            }
        } else {
            placeholder
        }
    }

    private var placeholder: some View {
        ZStack {
            Color.accentColor.opacity(0.15)
            Image(systemName: "magnifyingglass")
                .foregroundStyle(Color.accentColor)
        }
    }

    private func distLabel(_ m: Int) -> String {
        if m >= 1000 { return String(format: "%.1f km", Double(m) / 1000) }
        return "\(m) m"
    }
}

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

    @State private var name = ""
    @State private var rasse = ""
    @State private var beschreibung = ""
    @State private var dogs: [Dog] = []
    @State private var ownDogId: Int?
    @State private var photoSelection: [PhotosPickerItem] = []
    @State private var photoData: Data?

    @State private var saveState: SaveState = .idle
    @State private var errorMessage: String?

    private enum SaveState: Equatable {
        case idle
        case savingEntry
        case uploadingPhoto
    }

    var body: some View {
        NavigationStack {
            Form {
                Section("Hund") {
                    TextField("Name (z. B. Bello)", text: $name)
                    TextField("Rasse (optional)", text: $rasse)
                    if !dogs.isEmpty {
                        Picker("Eigener Hund", selection: $ownDogId) {
                            Text("Nicht meiner").tag(Int?.none)
                            ForEach(dogs) { dog in
                                Text(dog.name).tag(Int?.some(dog.id))
                            }
                        }
                    }
                }

                Section("Beschreibung") {
                    TextField("Auffälligkeiten, Halsband, Verhalten — alles was beim Wiederfinden hilft.",
                              text: $beschreibung, axis: .vertical)
                        .lineLimit(3...8)
                }

                Section {
                    PhotosPicker(selection: $photoSelection, maxSelectionCount: 1, matching: .images) {
                        Label(photoData == nil ? "Foto hinzufügen" : "Foto ändern",
                              systemImage: "photo.badge.plus")
                    }
                    if let photoData, let img = UIImage(data: photoData) {
                        Image(uiImage: img)
                            .resizable()
                            .scaledToFill()
                            .frame(maxHeight: 200)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                    }
                } header: {
                    Text("Foto")
                } footer: {
                    Text("Ein aktuelles Foto erhöht die Chance, dass jemand den Hund erkennt.")
                        .font(.caption2)
                }

                Section("Letzter bekannter Standort") {
                    Text(String(format: "%.5f, %.5f", coord.latitude, coord.longitude))
                        .font(.caption.monospacedDigit())
                        .foregroundStyle(.secondary)
                }

                if let errorMessage {
                    Section {
                        Text(errorMessage).font(.footnote).foregroundStyle(.red)
                    }
                }
            }
            .navigationTitle("Vermisst melden")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Abbrechen") { dismiss() }
                        .disabled(saveState != .idle)
                }
                ToolbarItem(placement: .confirmationAction) {
                    saveToolbarItem
                }
            }
            .onChange(of: photoSelection) { _, items in
                Task { await loadPhoto(from: items.first) }
            }
            .task { dogs = (try? await APIClient.shared.get("/api/dogs")) ?? [] }
            .interactiveDismissDisabled(saveState != .idle)
        }
    }

    @ViewBuilder
    private var saveToolbarItem: some View {
        switch saveState {
        case .idle:
            Button("Melden") { Task { await save() } }
                .disabled(name.trimmingCharacters(in: .whitespaces).isEmpty ||
                          beschreibung.trimmingCharacters(in: .whitespaces).count < 3)
        case .savingEntry, .uploadingPhoto:
            ProgressView()
        }
    }

    private func loadPhoto(from item: PhotosPickerItem?) async {
        guard let item else { return }
        photoData = try? await item.loadTransferable(type: Data.self)
    }

    private func save() async {
        errorMessage = nil
        saveState = .savingEntry

        let body = LostDogCreateBody(
            name: name.trimmingCharacters(in: .whitespaces),
            rasse: rasse.trimmingCharacters(in: .whitespaces).isEmpty ? nil : rasse,
            beschreibung: beschreibung.trimmingCharacters(in: .whitespacesAndNewlines),
            lat: coord.latitude,
            lon: coord.longitude,
            dogId: ownDogId
        )

        let created: LostDog
        do {
            created = try await APIClient.shared.post("/api/lost", body: body)
        } catch {
            errorMessage = error.localizedDescription
            saveState = .idle
            return
        }

        if let photoData {
            saveState = .uploadingPhoto
            let resized = ImageResize.resizedJPEG(from: photoData)
            do {
                _ = try await APIClient.shared.uploadFile(
                    "/api/lost/\(created.id)/foto",
                    filename: "lost_\(created.id).jpg",
                    data: resized
                )
            } catch {
                errorMessage = "Meldung ist gespeichert, aber Foto-Upload fehlgeschlagen: \(error.localizedDescription)"
                await onSaved()
                saveState = .idle
                return
            }
        }

        await onSaved()
        dismiss()
    }
}

private struct LostDogDetailView: View {
    let dog: LostDog

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                if let path = dog.fotoUrl,
                   let url = URL(string: "https://banyaro.app\(path)") {
                    AsyncImage(url: url) { phase in
                        switch phase {
                        case .success(let img):
                            img.resizable().scaledToFit()
                        default:
                            Rectangle().fill(.gray.opacity(0.15)).frame(height: 200)
                        }
                    }
                    .frame(maxHeight: 280)
                    .clipShape(RoundedRectangle(cornerRadius: 12))
                }

                VStack(alignment: .leading, spacing: 6) {
                    Text(dog.name).font(.title.bold())
                    if let r = dog.rasse, !r.isEmpty {
                        Text(r).font(.headline).foregroundStyle(.secondary)
                    }
                }

                Text(dog.beschreibung).font(.body)

                Map(initialPosition: .region(MKCoordinateRegion(
                    center: CLLocationCoordinate2D(latitude: dog.lat, longitude: dog.lon),
                    span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
                ))) {
                    Annotation(dog.name, coordinate: CLLocationCoordinate2D(latitude: dog.lat, longitude: dog.lon)) {
                        Image(systemName: "magnifyingglass.circle.fill")
                            .font(.title)
                            .foregroundStyle(.white, Color.accentColor)
                            .background(.white, in: Circle())
                    }
                }
                .frame(height: 240)
                .clipShape(RoundedRectangle(cornerRadius: 12))
                .allowsHitTesting(false)

                if let m = dog.melderName {
                    Label("Gemeldet von \(m)", systemImage: "person.fill")
                        .font(.caption).foregroundStyle(.secondary)
                }
            }
            .padding()
        }
        .navigationTitle("Vermisst")
        .navigationBarTitleDisplayMode(.inline)
    }
}
