import SwiftUI
import MapKit
import CoreLocation

struct GassiTreffenDetail: View {
    let meetingId: Int
    let fallbackTitle: String
    let onChange: () async -> Void

    @Environment(AuthSession.self) private var auth

    @State private var meeting: WalkMeeting?
    @State private var participants: WalkParticipantsResponse?
    @State private var location = OneShotLocation()
    @State private var isLoading = false
    @State private var errorMessage: String?
    @State private var isMutating = false
    @State private var dogs: [Dog] = []

    var body: some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 16) {
                if let meeting {
                    detailContent(meeting)
                } else if isLoading {
                    ProgressView().padding(.top, 60)
                } else if let errorMessage {
                    ContentUnavailableView(
                        "Fehler",
                        systemImage: "exclamationmark.triangle",
                        description: Text(errorMessage)
                    )
                    .padding(.top, 60)
                }
            }
            .padding()
        }
        .navigationTitle(meeting?.titel ?? fallbackTitle)
        .navigationBarTitleDisplayMode(.inline)
        .task {
            location.request()
            await load()
        }
    }

    @ViewBuilder
    private func detailContent(_ m: WalkMeeting) -> some View {
        treffpunktCard(m)
        navigationCard(m)

        VStack(alignment: .leading, spacing: 12) {
            HStack(alignment: .firstTextBaseline) {
                Image(systemName: "calendar")
                    .foregroundStyle(Color.accentColor)
                Text(formatDate(m.datum))
                    .font(.headline)
                Spacer()
                Text(m.uhrzeit)
                    .font(.headline.monospacedDigit())
            }

            if let veranstalter = m.veranstalterName {
                Label("von \(veranstalter)", systemImage: "person.circle.fill")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }

            if let beschreibung = m.beschreibung, !beschreibung.isEmpty {
                Text(beschreibung).font(.body).padding(.top, 4)
            }
        }
        .padding(14)
        .background(.background.secondary, in: RoundedRectangle(cornerRadius: 12))

        teilnehmerSection(m)

        if !isOwn(m) {
            joinButton(m)
        } else {
            ownerBadge
        }

        Text("Fotos vom Treffen kannst du später in der banyaro.app teilen.")
            .font(.caption2)
            .foregroundStyle(.tertiary)
            .frame(maxWidth: .infinity)

        if let errorMessage {
            Text(errorMessage)
                .font(.footnote)
                .foregroundStyle(.red)
        }
    }

    // MARK: - Treffpunkt card

    private func treffpunktCard(_ m: WalkMeeting) -> some View {
        Map(initialPosition: .region(MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: m.lat, longitude: m.lon),
            span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02)
        ))) {
            UserAnnotation()
            Annotation(m.titel, coordinate: CLLocationCoordinate2D(latitude: m.lat, longitude: m.lon)) {
                Image(systemName: "pawprint.circle.fill")
                    .font(.title)
                    .foregroundStyle(.white, Color.accentColor)
                    .background(.white, in: Circle())
                    .shadow(radius: 2)
            }
        }
        .frame(height: 240)
        .clipShape(RoundedRectangle(cornerRadius: 16))
        .allowsHitTesting(false)
    }

    // MARK: - Navigation row

    private func navigationCard(_ m: WalkMeeting) -> some View {
        HStack(spacing: 12) {
            Image(systemName: "mappin.and.ellipse")
                .font(.title2)
                .foregroundStyle(Color.accentColor)
                .frame(width: 32)
            VStack(alignment: .leading, spacing: 2) {
                Text(m.ortName ?? "Treffpunkt")
                    .font(.subheadline.bold())
                if let dist = distanceLabel(to: m) {
                    Text(dist)
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
            }
            Spacer()
            Button {
                openInMaps(m)
            } label: {
                HStack(spacing: 4) {
                    Image(systemName: "arrow.triangle.turn.up.right.diamond.fill")
                    Text("Route").bold()
                }
                .font(.subheadline)
                .padding(.horizontal, 12)
                .padding(.vertical, 8)
                .background(Color.accentColor, in: Capsule())
                .foregroundStyle(.white)
            }
        }
        .padding(14)
        .background(.background.secondary, in: RoundedRectangle(cornerRadius: 12))
    }

    // MARK: - Teilnehmer

    @ViewBuilder
    private func teilnehmerSection(_ m: WalkMeeting) -> some View {
        VStack(alignment: .leading, spacing: 10) {
            HStack {
                Label("Teilnehmer", systemImage: "person.2.fill")
                    .font(.headline)
                Spacer()
                Text("\(m.teilnehmerCount ?? 0) / \(m.maxTeilnehmer)")
                    .font(.subheadline.bold().monospacedDigit())
                    .foregroundStyle(.secondary)
            }

            if let yes = participants?.invitations.filter({ $0.status == "yes" }), !yes.isEmpty {
                ForEach(yes) { p in
                    participantRow(p)
                }
            } else {
                Text("Noch niemand zugesagt — sei der/die Erste.")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
        }
        .padding(14)
        .background(.background.secondary, in: RoundedRectangle(cornerRadius: 12))
    }

    private func participantRow(_ p: WalkInvitation) -> some View {
        HStack(spacing: 10) {
            Image(systemName: "person.circle.fill")
                .foregroundStyle(Color.accentColor)
            VStack(alignment: .leading, spacing: 2) {
                Text(p.userName ?? "Teilnehmer").font(.subheadline.bold())
                if let hunde = p.hunde, !hunde.isEmpty {
                    Text(hunde).font(.caption).foregroundStyle(.secondary)
                }
            }
            Spacer()
        }
    }

    // MARK: - Join / leave

    private var hasJoined: Bool {
        participants?.myRsvp == "yes"
    }

    private func joinButton(_ m: WalkMeeting) -> some View {
        Button {
            Task { await toggleJoin() }
        } label: {
            HStack {
                Image(systemName: hasJoined ? "person.crop.circle.badge.minus" : "person.crop.circle.badge.plus")
                Text(hasJoined ? "Doch nicht teilnehmen" : "Ich bin dabei").bold()
            }
            .frame(maxWidth: .infinity, minHeight: 50)
        }
        .background(hasJoined ? Color.red : Color.accentColor, in: Capsule())
        .foregroundStyle(.white)
        .disabled(isMutating)
    }

    private var ownerBadge: some View {
        Label("Dein Treffen", systemImage: "person.badge.shield.checkmark.fill")
            .font(.subheadline.bold())
            .padding(.vertical, 12)
            .frame(maxWidth: .infinity)
            .background(Color.accentColor.opacity(0.15), in: Capsule())
            .foregroundStyle(Color.accentColor)
    }

    // MARK: - Helpers

    private func isOwn(_ m: WalkMeeting) -> Bool {
        m.userId == auth.profile?.id
    }

    private func distanceLabel(to m: WalkMeeting) -> String? {
        guard let me = location.coordinate else { return nil }
        let here = CLLocation(latitude: me.latitude, longitude: me.longitude)
        let there = CLLocation(latitude: m.lat, longitude: m.lon)
        let meters = there.distance(from: here)
        if meters < 1000 {
            return "\(Int(meters)) m entfernt"
        }
        return String(format: "%.1f km entfernt", meters / 1000)
    }

    private func openInMaps(_ m: WalkMeeting) {
        let placemark = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: m.lat, longitude: m.lon))
        let item = MKMapItem(placemark: placemark)
        item.name = m.ortName?.isEmpty == false ? m.ortName : m.titel
        // Default mode lets the user pick walking/driving in Apple Maps
        item.openInMaps(launchOptions: nil)
    }

    private func load() async {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }
        async let detail: WalkMeeting? = try? APIClient.shared.get("/api/walks/\(meetingId)")
        async let parts: WalkParticipantsResponse? = try? APIClient.shared.get("/api/walks/\(meetingId)/participants")
        meeting = await detail
        participants = await parts
        if dogs.isEmpty {
            dogs = (try? await APIClient.shared.get("/api/dogs")) ?? []
        }
    }

    private func toggleJoin() async {
        isMutating = true
        errorMessage = nil
        defer { isMutating = false }
        do {
            if hasJoined {
                try await APIClient.shared.delete("/api/walks/\(meetingId)/join")
            } else {
                let body = WalkJoinBody(dogIds: dogs.map { $0.id })
                let _: WalkMeeting = try await APIClient.shared.post("/api/walks/\(meetingId)/join", body: body)
            }
            await onChange()
            await load()
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    private func formatDate(_ s: String) -> String {
        let parser = DateFormatter()
        parser.locale = Locale(identifier: "en_US_POSIX")
        parser.dateFormat = "yyyy-MM-dd"
        if let d = parser.date(from: String(s.prefix(10))) {
            let out = DateFormatter()
            out.locale = Locale(identifier: "de_DE")
            out.dateStyle = .full
            return out.string(from: d)
        }
        return s
    }
}
