import SwiftUI
import HealthKit
import HealthKitExtensions
import HealthDB
import CoreLocation

struct ActivityDetailView: View {

    @EnvironmentObject
    var database: Database

    let workout: Workout

    let activity: HKWorkoutActivity

    @State
    private var statistics: [(type: HKQuantityType, statistics: Statistics)] = []

    @State
    private var privateMetadata: [(key: String, value: Any)] = []

    @State
    private var showErrorMessage = false

    @State
    private var errorMessage: String = ""

    private var metadata: [(key: String, value: Any)] {
        activity.metadata?.sorted { $0.key } ?? []
    }

    var body: some View {
        List {
            Section("Properties") {
                DetailRow("UUID", value: activity.uuid)
                DetailRow("Activity", value: activity.workoutConfiguration.activityType)
                DetailRow("Location", value: activity.workoutConfiguration.locationType)
                DetailRow("Swimming Location", value: activity.workoutConfiguration.swimmingLocationType)
                DetailRow("Lap Length", value: activity.workoutConfiguration.lapLength)
                DetailRow("Start", date: activity.startDate)
                DetailRow("End", date: activity.endDate)
                DetailRow("Duration", duration: activity.duration)
            }
            if !statistics.isEmpty {
                Section("Statistics") {
                    ForEach(statistics, id: \.type) { (type, statistic) in
                        let name = HKQuantityTypeIdentifier(rawValue: type.identifier).description
                        DetailRow(name, value: statistic.average)
                    }
                }
            }
            if !(activity.metadata?.isEmpty ?? true) {
                Section("Metadata") {
                    ForEach(metadata, id: \.key) { (key, value) in
                        DetailRow(MetadataKeyName(key), value: "\(value)")
                    }
                }
            }
            if !privateMetadata.isEmpty {
                Section("Private Metadata") {
                    ForEach(privateMetadata, id:\.key) { (key, value) in
                        DetailRow(MetadataKeyName(key), value: "\(value)")
                    }
                }
            }
        }
        .navigationTitle("Activity")
        .onAppear(perform: load)
        .alert("Processing error", isPresented: $showErrorMessage) {
            Button("Dismiss", role: .cancel) { }
        } message: {
            Text(errorMessage)
        }
    }

    private func show(_ error: String) {
        DispatchQueue.main.async {
            self.errorMessage = error
            self.showErrorMessage = true
        }
    }

    private func load() {
        guard let store = database.store else {
            return
        }
        Task {
            await loadStatistics(db: store)
            await loadPrivateMetadata(db: store)
        }
    }

    private func loadStatistics(db: HealthDatabase) async {
        do {
            let statistics = try db.store.statistics(associatedWith: activity)
            DispatchQueue.main.async {
                self.statistics = statistics
                    .sorted { $0.key.description }
                    .map { ($0, $1) }
            }
        } catch {
            print("Failed to load statistics from database: \(error)")
        }
    }

    private func loadPrivateMetadata(db: HealthDatabase) async {
        do {
            let metadata = try db.store.metadata(for: workout.uuid, includePrivateMetadata: true)
                .filter { $0.key.hasPrefix("_HKPrivate") }
            DispatchQueue.main.async {
                self.privateMetadata = metadata.sorted { $0.key }
            }
        } catch {
            show("Failed to load private metadata from database: \(error)")
        }
    }

}

#Preview {
    NavigationStack {
        ActivityDetailView(workout: .mock1, activity: .mock1)
            .environmentObject(Database.empty)
    }
}
