import SwiftUI
import HealthKit
import HealthDB
import SFSafeSymbols

struct WorkoutTab: View {

    @EnvironmentObject
    var database: Database

    @State var navigationPath: NavigationPath = .init()

    @State var filteredActivityType: HKWorkoutActivityType? = nil

    @State var workouts: [(title: String, workouts: [Workout])] = []

    @State var workoutTypeCounts: [(type: HKWorkoutActivityType, count: Int)] = []

    var body: some View {
        NavigationStack(path: $navigationPath) {
            VStack {
                List {
                    WorkoutTypeSelection(selected: $filteredActivityType, available: $workoutTypeCounts)
                        .listRowSeparator(.hidden)
                    ForEach(workouts, id: \.title) { month in
                        Section {
                            ForEach(month.workouts) { workout in
                                WorkoutListRow(workout: workout)
                                    .overlay(
                                        NavigationLink(value: workout) { }
                                            .opacity(0))
                                    .listRowSeparator(.hidden)
                                    .listRowInsets(.init(top: 0, leading: 16, bottom: 5, trailing: 16))
                            }
                        } header: {
                            Text(month.title)
                                .font(.title3)
                                .fontWeight(.bold)
                                .foregroundStyle(.primary)
                        } footer: {
                            Text("")
                        }
                    }
                }
                .listStyle(.plain)
            }
            .navigationTitle("Workouts")
            .navigationDestination(for: Workout.self) {
                WorkoutDetailView(workout: $0)
            }
            .refreshable {
                reloadAsync()
            }
            .onChange(of: database.file, reload)
            .onChange(of: filteredActivityType, reload)
            .onAppear(perform: {
                if workouts.isEmpty {
                    reload()
                }
            })
        }
        .preferredColorScheme(.dark)
    }

    private func reload() {
        Task {
            reloadAsync()
        }
    }

    private func reloadAsync() {
        guard let store = database.store else {
            DispatchQueue.main.async {
                self.workouts = []
                self.workoutTypeCounts = []
            }
            return
        }
        loadWorkoutTypes(in: store)
        loadWorkouts(in: store)
    }

    private func loadWorkouts(in store: HealthDatabase) {
        do {
            let workouts: [Workout]
            if let filteredActivityType {
                workouts = try store.workouts(type: filteredActivityType)
            } else {
                workouts = try store.workouts()
            }
            print("Loaded \(workouts.count) workouts")

            let calendar = Calendar.current
            var sortedIntoMonths = [(title: String, workouts: [Workout])]()
            var currentMonth: String? = nil
            var currentWorkouts = [Workout]()
            for workout in workouts.sorted(ascending: false, using: { $0.endDate }) {
                let date = workout.endDate
                let month = calendar.component(.month, from: date)
                let year = calendar.component(.year, from: date)
                let title = "\(calendar.monthSymbols[month-1]) \(year)"
                guard let lastMonth = currentMonth else {
                    currentMonth = title
                    currentWorkouts = [workout]
                    continue
                }
                guard lastMonth == title else {
                    sortedIntoMonths.append((lastMonth, currentWorkouts))
                    currentMonth = title
                    currentWorkouts = [workout]
                    continue
                }
                currentWorkouts.append(workout)
            }
            if let currentMonth, !currentWorkouts.isEmpty {
                sortedIntoMonths.append((currentMonth, currentWorkouts))
            }

            DispatchQueue.main.async {
                self.workouts = sortedIntoMonths
            }
        } catch {
            print("Failed to load workouts: \(error)")
            DispatchQueue.main.async {
                self.workouts = []
            }
        }
    }

    private func loadWorkoutTypes(in store: HealthDatabase) {
        do {
            let types = try store.store.workoutTypeFrequencies()
                .sorted(ascending: false) { $0.value }
                .map { (type: $0.key, count: $0.value) }
            DispatchQueue.main.async {
                self.workoutTypeCounts = types
            }
        } catch {
            print("Failed to get workout frequencies: \(error)")
            DispatchQueue.main.async {
                self.workoutTypeCounts = []
            }
        }
    }
}

#Preview {
    WorkoutTab()
        .environmentObject(Database.empty)
}
