import SwiftUI
import SwiftData
import MapKit

struct TrackingView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var activeWalks: [ActiveWalk]

    @State private var tracker = LocationTracker()
    @State private var now: Date = .now
    @State private var pendingPhotos: [CapturedPhoto] = []

    @State private var showFinishSheet = false
    @State private var showCamera = false
    @State private var showResumeDialog = false
    @State private var didCheckResume = false

    private let clockTicker = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    private let persistTicker = Timer.publish(every: 5, on: .main, in: .common).autoconnect()

    var body: some View {
        NavigationStack {
            Group {
                if tracker.isTracking {
                    activeTracking
                } else {
                    startScreen
                }
            }
            .navigationTitle("Aufnehmen")
            .navigationBarTitleDisplayMode(.inline)
        }
        .onReceive(clockTicker) { now = $0 }
        .onReceive(persistTicker) { _ in
            tracker.checkAutoPause()
            persistActive()
            updateLiveActivity()
        }
        .onChange(of: tracker.isTracking) { _, isTracking in
            if isTracking {
                startLiveActivity()
            } else {
                WalkActivityController.end()
            }
        }
        .onChange(of: tracker.isPaused) { _, _ in updateLiveActivity() }
        .onChange(of: tracker.isAutoPaused) { _, _ in updateLiveActivity() }
        .onAppear { offerResumeIfNeeded() }
        .sheet(isPresented: $showFinishSheet) {
            FinishWalkSheet(
                points: tracker.points,
                durationSeconds: tracker.effectiveElapsedSeconds,
                distanceMeters: tracker.totalDistanceMeters,
                initialPhotos: pendingPhotos,
                onDiscard: { discardCurrentWalk() },
                onSaved: { discardCurrentWalk() }
            )
        }
        .fullScreenCover(isPresented: $showCamera) {
            CameraPicker { data in
                let location = tracker.points.last
                pendingPhotos.append(CapturedPhoto(data: data, location: location))
            }
            .ignoresSafeArea()
        }
        .confirmationDialog(
            resumeDialogTitle,
            isPresented: $showResumeDialog,
            titleVisibility: .visible
        ) {
            Button("Tour fortsetzen") { resumeStoredWalk() }
            Button("Jetzt speichern") { loadStoredWalkIntoTracker(thenFinish: true) }
            Button("Verwerfen", role: .destructive) { deleteStoredWalk() }
        } message: {
            if let stored = activeWalks.first {
                Text("\(stored.points.count) Punkte aufgezeichnet, gestartet um \(formatTime(stored.startedAt)).")
            }
        }
    }

    // MARK: - Active tracking

    private var activeTracking: some View {
        ZStack(alignment: .top) {
            Map {
                UserAnnotation()
                if tracker.points.count >= 2 {
                    MapPolyline(coordinates: tracker.points.map {
                        CLLocationCoordinate2D(latitude: $0.lat, longitude: $0.lon)
                    })
                    .stroke(Color.accentColor, style: StrokeStyle(lineWidth: 5, lineJoin: .round))
                }
            }
            .mapStyle(.standard(elevation: .flat, pointsOfInterest: .excludingAll))
            .mapControlVisibility(.hidden)
            .ignoresSafeArea(edges: .bottom)

            VStack {
                statsCard
                Spacer()
                bottomControls
                    .padding(.bottom, 12)
            }
            .padding(.horizontal)

            cameraOverlayButton
        }
    }

    private var statsCard: some View {
        HStack(spacing: 0) {
            stat(
                value: String(format: "%.2f", tracker.totalDistanceMeters / 1000),
                unit: "km",
                label: "Distanz"
            )
            divider
            stat(value: formatDuration(tracker.effectiveElapsedSeconds), unit: "", label: "Dauer")
            divider
            stat(value: "\(pendingPhotos.count)", unit: "", label: "Fotos")
        }
        .padding()
        .background(.regularMaterial, in: RoundedRectangle(cornerRadius: 16))
        .overlay(alignment: .topLeading) {
            if tracker.isPaused {
                badge("Pause", icon: "pause.circle.fill", color: .orange).padding(8)
            } else if tracker.isAutoPaused {
                badge("Auto-Pause", icon: "pause.circle", color: .gray).padding(8)
            }
        }
    }

    private func badge(_ text: String, icon: String, color: Color) -> some View {
        Label(text, systemImage: icon)
            .font(.caption.bold())
            .foregroundStyle(.white)
            .padding(.horizontal, 8)
            .padding(.vertical, 4)
            .background(color, in: Capsule())
    }

    private var divider: some View {
        Divider().frame(height: 36)
    }

    private func stat(value: String, unit: String, label: String) -> some View {
        VStack(spacing: 4) {
            HStack(alignment: .firstTextBaseline, spacing: 2) {
                Text(value).font(.title2.bold().monospacedDigit())
                if !unit.isEmpty {
                    Text(unit).font(.callout).foregroundStyle(.secondary)
                }
            }
            Text(label).font(.caption).foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity)
    }

    private var cameraOverlayButton: some View {
        VStack {
            Spacer()
            HStack {
                Spacer()
                Button {
                    showCamera = true
                } label: {
                    Image(systemName: "camera.fill")
                        .font(.title2)
                        .foregroundStyle(.white)
                        .frame(width: 56, height: 56)
                        .background(Color.accentColor, in: Circle())
                        .shadow(radius: 4)
                }
                .padding(.trailing, 20)
                .padding(.bottom, 100) // sit above the bottom controls
            }
        }
        .allowsHitTesting(true)
    }

    private var bottomControls: some View {
        HStack(spacing: 12) {
            Button {
                if tracker.isPaused { tracker.resume() } else { tracker.pause() }
                persistActive()
            } label: {
                Image(systemName: tracker.isPaused ? "play.fill" : "pause.fill")
                    .font(.title3.bold())
                    .frame(width: 56, height: 56)
                    .foregroundStyle(.white)
                    .background(tracker.isPaused ? Color.accentColor : Color.orange, in: Circle())
            }

            Button {
                tracker.stop()
                showFinishSheet = true
            } label: {
                HStack {
                    Image(systemName: "stop.circle.fill")
                    Text("Stoppen").bold()
                }
                .frame(maxWidth: .infinity, minHeight: 56)
            }
            .background(.red, in: Capsule())
            .foregroundStyle(.white)
        }
    }

    // MARK: - Start screen

    private var startScreen: some View {
        VStack(spacing: 28) {
            Spacer()
            Image(systemName: "figure.walk.circle.fill")
                .font(.system(size: 96))
                .foregroundStyle(Color.accentColor)
            VStack(spacing: 6) {
                Text("Bereit für die nächste Gassi?")
                    .font(.title3.bold())
                Text("Tippe auf Start, um deine Tour aufzuzeichnen — auch wenn dein iPhone gesperrt ist.")
                    .multilineTextAlignment(.center)
                    .foregroundStyle(.secondary)
                    .padding(.horizontal)
            }

            if tracker.permissionDenied {
                permissionWarning
            }

            Button {
                startFresh()
            } label: {
                HStack {
                    Image(systemName: "play.fill")
                    Text("Aufnahme starten").bold()
                }
                .frame(maxWidth: .infinity, minHeight: 56)
            }
            .background(Color.accentColor, in: Capsule())
            .foregroundStyle(.white)
            .padding(.horizontal)

            Spacer()
        }
    }

    private var permissionWarning: some View {
        VStack(spacing: 6) {
            Label("Standortzugriff fehlt", systemImage: "location.slash.fill")
                .font(.subheadline.bold())
                .foregroundStyle(.red)
            Text("Bitte erlaube den Standortzugriff in den iOS-Einstellungen unter Datenschutz → Ortungsdienste → Ban Yaro Go.")
                .font(.footnote)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)
                .padding(.horizontal)
        }
    }

    // MARK: - Walk lifecycle

    private func startFresh() {
        // Discard any existing stale ActiveWalk before starting a new one
        for w in activeWalks { modelContext.delete(w) }
        let walk = ActiveWalk(startedAt: .now)
        modelContext.insert(walk)
        try? modelContext.save()
        pendingPhotos = []
        tracker.startOrRequest()
    }

    private func offerResumeIfNeeded() {
        guard !didCheckResume else { return }
        didCheckResume = true
        if !activeWalks.isEmpty, !tracker.isTracking {
            showResumeDialog = true
        }
    }

    private func resumeStoredWalk() {
        guard let walk = activeWalks.first else { return }
        tracker.restore(
            startedAt: walk.startedAt,
            points: walk.points,
            accumulatedPausedSeconds: walk.accumulatedPausedSeconds,
            lastUpdate: walk.lastUpdate,
            wasPaused: walk.isPaused
        )
        pendingPhotos = []
    }

    private func loadStoredWalkIntoTracker(thenFinish: Bool) {
        guard let walk = activeWalks.first else { return }
        // Mirror walk state into tracker without actually starting GPS — we
        // just need the data for FinishWalkSheet.
        tracker.restore(
            startedAt: walk.startedAt,
            points: walk.points,
            accumulatedPausedSeconds: walk.accumulatedPausedSeconds,
            lastUpdate: walk.lastUpdate,
            wasPaused: true // prevent automatic GPS restart
        )
        tracker.stop()
        pendingPhotos = []
        if thenFinish {
            showFinishSheet = true
        }
    }

    private func deleteStoredWalk() {
        for w in activeWalks { modelContext.delete(w) }
        try? modelContext.save()
    }

    private func discardCurrentWalk() {
        // Called after FinishWalkSheet onSaved or onDiscard. Resets state.
        deleteStoredWalk()
        tracker = LocationTracker()
        pendingPhotos = []
    }

    private func persistActive() {
        guard tracker.isTracking, let walk = activeWalks.first else { return }
        walk.points = tracker.points
        walk.accumulatedPausedSeconds = tracker.accumulatedPausedSeconds
        walk.pausedAt = tracker.isPaused ? (tracker.pausedAt ?? .now) : nil
        walk.lastUpdate = .now
        try? modelContext.save()
    }

    // MARK: - Helpers

    private func startLiveActivity() {
        guard let startedAt = tracker.startedAt else { return }
        WalkActivityController.start(
            startedAt: startedAt,
            initialState: liveActivityState()
        )
    }

    private func updateLiveActivity() {
        guard tracker.isTracking else { return }
        WalkActivityController.update(liveActivityState())
    }

    private func liveActivityState() -> WalkActivityAttributes.WalkActivityState {
        WalkActivityAttributes.WalkActivityState(
            distanceMeters: tracker.totalDistanceMeters,
            elapsedSeconds: tracker.effectiveElapsedSeconds,
            pointCount: tracker.points.count,
            isPaused: tracker.isPaused,
            isAutoPaused: tracker.isAutoPaused
        )
    }

    private func formatDuration(_ seconds: Int) -> String {
        let h = seconds / 3600
        let m = (seconds % 3600) / 60
        let s = seconds % 60
        if h > 0 { return String(format: "%d:%02d:%02d", h, m, s) }
        return String(format: "%d:%02d", m, s)
    }

    private func formatTime(_ date: Date) -> String {
        let f = DateFormatter()
        f.locale = Locale(identifier: "de_DE")
        f.dateStyle = .short
        f.timeStyle = .short
        return f.string(from: date)
    }

    private var resumeDialogTitle: String {
        guard let stored = activeWalks.first else { return "" }
        return "Tour nicht gespeichert (\(formatTime(stored.startedAt)))"
    }
}
