//
// WorkoutLogListView.swift
// Workouts Watch App
//
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
//

import SwiftUI
import SwiftData

struct WorkoutLogListView: View {
    @Environment(WatchConnectivityBridge.self) private var bridge

    /// The split this workout came from (read-only on the watch), used to offer
    /// additional exercises that aren't logged yet.
    @Query private var matchingSplits: [Split]

    /// Working copy of the workout. We drive the UI from this and mutate it on
    /// every edit (then forward through the bridge) to avoid the read-after-write
    /// race against the cache, which lags local writes by a beat.
    @State private var doc: WorkoutDocument

    @State private var showingExercisePicker = false
    @State private var selectedLogID: String?

    init(workout: Workout) {
        _doc = State(initialValue: WorkoutDocument(from: workout))
        if let splitID = workout.splitID {
            _matchingSplits = Query(filter: #Predicate<Split> { $0.id == splitID })
        } else {
            // No source split: never match anything.
            _matchingSplits = Query(filter: #Predicate<Split> { _ in false })
        }
    }

    private var split: Split? { matchingSplits.first }

    private var sortedLogs: [WorkoutLogDocument] {
        doc.logs.sorted { $0.order < $1.order }
    }

    private var availableExercises: [Exercise] {
        guard let split else { return [] }
        let existingNames = Set(doc.logs.map { $0.exerciseName })
        return split.exercisesArray.filter { !existingNames.contains($0.name) }
    }

    var body: some View {
        List {
            Section(header: Text(label)) {
                ForEach(sortedLogs) { log in
                    Button {
                        selectedLogID = log.id
                    } label: {
                        WorkoutLogRowLabel(log: log)
                    }
                    .buttonStyle(.plain)
                }
            }

            if !availableExercises.isEmpty {
                Section {
                    Button {
                        showingExercisePicker = true
                    } label: {
                        HStack {
                            Image(systemName: "plus.circle.fill")
                                .foregroundColor(.green)
                            Text("Add Exercise")
                        }
                    }
                }
            }
        }
        .overlay {
            if sortedLogs.isEmpty {
                ContentUnavailableView(
                    "No Exercises",
                    systemImage: "figure.strengthtraining.traditional",
                    description: Text(availableExercises.isEmpty
                        ? "No exercises in this workout."
                        : "Tap + to add exercises.")
                )
            }
        }
        .navigationTitle(doc.splitName ?? Split.unnamed)
        .navigationDestination(item: $selectedLogID) { logID in
            ExerciseProgressView(doc: $doc, logID: logID, onChange: { bridge.update(workout: doc) })
        }
        .sheet(isPresented: $showingExercisePicker) {
            ExercisePickerView(exercises: availableExercises) { exercise in
                addExercise(exercise)
            }
        }
    }

    private var label: String {
        let start = doc.start
        if doc.status == WorkoutStatus.completed.rawValue, let end = doc.end {
            if start.isSameDay(as: end) {
                return "\(start.formattedDate())—\(end.formattedTime())"
            } else {
                return "\(start.formattedDate())—\(end.formattedDate())"
            }
        }
        return start.formattedDate()
    }

    private func addExercise(_ exercise: Exercise) {
        let newLog = WorkoutLogDocument(
            id: ULID.make(),
            exerciseName: exercise.name,
            order: doc.logs.count,
            sets: exercise.sets,
            reps: exercise.reps,
            weight: exercise.weight,
            loadType: exercise.loadType,
            durationSeconds: exercise.durationTotalSeconds,
            currentStateIndex: 0,
            completed: false,
            status: WorkoutStatus.notStarted.rawValue,
            notes: nil,
            date: doc.start
        )
        doc.logs.append(newLog)
        doc.updatedAt = Date()
        bridge.update(workout: doc)
        showingExercisePicker = false
    }
}

// MARK: - Workout Log Row Label

struct WorkoutLogRowLabel: View {
    let log: WorkoutLogDocument

    var body: some View {
        HStack {
            statusIcon
                .foregroundColor(statusColor)

            VStack(alignment: .leading, spacing: 2) {
                Text(log.exerciseName)
                    .font(.headline)
                    .lineLimit(1)

                Text(subtitle)
                    .font(.caption2)
                    .foregroundColor(.secondary)
            }

            Spacer()
        }
    }

    private var status: WorkoutStatus {
        WorkoutStatus(rawValue: log.status) ?? .notStarted
    }

    private var statusIcon: Image {
        switch status {
        case .completed:
            Image(systemName: "checkmark.circle.fill")
        case .inProgress:
            Image(systemName: "circle.dotted")
        case .notStarted:
            Image(systemName: "circle")
        case .skipped:
            Image(systemName: "xmark.circle")
        }
    }

    private var statusColor: Color {
        switch status {
        case .completed:
            .accentColor
        case .inProgress:
            .gray
        case .notStarted:
            .secondary
        case .skipped:
            .secondary
        }
    }

    private var subtitle: String {
        if LoadType(rawValue: log.loadType) == .duration {
            let mins = log.durationSeconds / 60
            let secs = log.durationSeconds % 60
            if mins > 0 && secs > 0 {
                return "\(log.sets) × \(mins)m \(secs)s"
            } else if mins > 0 {
                return "\(log.sets) × \(mins) min"
            } else {
                return "\(log.sets) × \(secs) sec"
            }
        } else {
            return "\(log.sets) × \(log.reps) × \(log.weight) lbs"
        }
    }
}

// MARK: - Exercise Picker View

struct ExercisePickerView: View {
    @Environment(\.dismiss) private var dismiss

    let exercises: [Exercise]
    let onSelect: (Exercise) -> Void

    var body: some View {
        NavigationStack {
            List {
                if exercises.isEmpty {
                    Text("All exercises added")
                        .foregroundColor(.secondary)
                } else {
                    ForEach(exercises) { exercise in
                        Button {
                            onSelect(exercise)
                            dismiss()
                        } label: {
                            VStack(alignment: .leading) {
                                Text(exercise.name)
                                    .font(.headline)
                                Text(exerciseSubtitle(exercise))
                                    .font(.caption2)
                                    .foregroundColor(.secondary)
                            }
                        }
                    }
                }
            }
            .navigationTitle("Add Exercise")
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") {
                        dismiss()
                    }
                }
            }
        }
    }

    private func exerciseSubtitle(_ exercise: Exercise) -> String {
        if exercise.loadTypeEnum == .duration {
            let mins = exercise.durationMinutes
            let secs = exercise.durationSeconds
            if mins > 0 && secs > 0 {
                return "\(exercise.sets) × \(mins)m \(secs)s"
            } else if mins > 0 {
                return "\(exercise.sets) × \(mins) min"
            } else {
                return "\(exercise.sets) × \(secs) sec"
            }
        } else {
            return "\(exercise.sets) × \(exercise.reps) × \(exercise.weight) lbs"
        }
    }
}
