//
// ExerciseAddEditView.swift
// Workouts
//
// Created by rzen on 7/15/25 at 7:12 AM.
//
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
//

import SwiftUI
import SwiftData

struct ExerciseAddEditView: View {
    @Environment(SyncEngine.self) private var sync
    @Environment(\.dismiss) private var dismiss

    @State private var showingExercisePicker = false

    // The exercise entity provides initial values (read-only).
    let exercise: Exercise
    // The parent routine is needed to rebuild and save the RoutineDocument.
    let routine: Routine

    // Local editable state
    @State private var exerciseName: String
    // The library exercise this row derives from — nil only when `exerciseName`
    // doesn't (yet) match any bundled exercise. Set alongside `exerciseName` when
    // the picker is used; carried through unchanged when the user just retypes the
    // name in the TextField, so a rename keeps its figure/info link.
    @State private var libraryName: String?
    @State private var loadType: LoadType
    @State private var minutes: Int
    @State private var seconds: Int
    @State private var weightTens: Int
    @State private var weightOnes: Int
    @State private var reps: Int
    @State private var sets: Int
    // Machine comfort settings. `machineEnabled` mirrors the optionality of the
    // stored `machineSettings` — ON persists a (possibly empty) array, OFF persists
    // nil. `machineSettings` holds the ordered rows while the toggle is on.
    @State private var machineEnabled: Bool
    @State private var machineSettings: [MachineSetting]
    @AppStorage("weightUnit") private var weightUnit: WeightUnit = .lb

    init(exercise: Exercise, routine: Routine) {
        self.exercise = exercise
        self.routine = routine

        // The tens/ones pickers step whole values; a fractional stored weight
        // shows (and saves back) its whole part until UX #3's UI lands.
        let w = Int(exercise.weight)
        _exerciseName = State(initialValue: exercise.name)
        _libraryName = State(initialValue: exercise.libraryName
            ?? (ExerciseMotionLibrary.exerciseNames.contains(exercise.name) ? exercise.name : nil))
        _loadType = State(initialValue: exercise.loadTypeEnum)
        _minutes = State(initialValue: exercise.durationMinutes)
        _seconds = State(initialValue: exercise.durationSeconds)
        _weightTens = State(initialValue: (w / 10) * 10)
        _weightOnes = State(initialValue: w % 10)
        _reps = State(initialValue: exercise.reps)
        _sets = State(initialValue: exercise.sets)
        _machineEnabled = State(initialValue: exercise.machineSettings != nil)
        _machineSettings = State(initialValue: exercise.machineSettings ?? [])
    }

    var body: some View {
        NavigationStack {
            Form {
                Section(
                    header: Text("Exercise"),
                    footer: Text("You can rename this exercise for this routine — for example \"Warmup Walk\" for Treadmill. The animated figure and exercise guide still come from the original exercise.")
                ) {
                    if exerciseName.isEmpty {
                        Button(action: {
                            showingExercisePicker = true
                        }) {
                            HStack {
                                Text("Select Exercise")
                                Spacer()
                                Image(systemName: "chevron.right")
                                    .foregroundColor(.gray)
                            }
                        }
                    } else {
                        if let libraryName {
                            ListItem(title: libraryName)
                        }
                        TextField("Name", text: $exerciseName)
                    }
                }

                Section(header: Text("Sets/Reps")) {
                    HStack(alignment: .bottom) {
                        VStack(alignment: .center) {
                            Text("Sets")
                            Picker("", selection: $sets) {
                                ForEach(0..<20) { s in
                                    Text("\(s)").tag(s)
                                }
                            }
                            .frame(height: 100)
                            .pickerStyle(.wheel)
                        }
                        VStack(alignment: .center) {
                            Text("Reps")
                            Picker("", selection: $reps) {
                                ForEach(0..<100) { r in
                                    Text("\(r)").tag(r)
                                }
                            }
                            .frame(height: 100)
                            .pickerStyle(.wheel)
                        }
                    }
                }

                Section(
                    header: Text("Load Type"),
                    footer: Text("For bodyweight exercises choose None. For resistance or weight training select Weight. For exercises that are time oriented (like plank or meditation) select Time.")
                ) {
                    Picker("", selection: $loadType) {
                        ForEach(LoadType.allCases, id: \.self) { load in
                            Text(load.name)
                                .tag(load)
                        }
                    }
                    .pickerStyle(.segmented)
                }

                if loadType == .weight {
                    Section(header: Text("Weight")) {
                        HStack {
                            Picker("", selection: $weightTens) {
                                ForEach(0..<100) { lbs in
                                    Text("\(lbs * 10)").tag(lbs * 10)
                                }
                            }
                            .frame(height: 100)
                            .pickerStyle(.wheel)

                            Picker("", selection: $weightOnes) {
                                ForEach(0..<10) { lbs in
                                    Text("\(lbs)").tag(lbs)
                                }
                            }
                            .frame(height: 100)
                            .pickerStyle(.wheel)

                            Text(weightUnit.abbreviation)
                        }
                    }
                }

                if loadType == .duration {
                    Section(header: Text("Duration")) {
                        HStack {
                            Picker("Minutes", selection: $minutes) {
                                ForEach(0..<60) { minute in
                                    Text("\(minute) min").tag(minute)
                                }
                            }
                            .pickerStyle(.wheel)

                            Picker("Seconds", selection: $seconds) {
                                ForEach(0..<60) { second in
                                    Text("\(second) sec").tag(second)
                                }
                            }
                            .pickerStyle(.wheel)
                        }
                    }
                }

                Section(
                    header: Text("Machine"),
                    footer: Text("Turn on for machine-based exercises to record comfort settings (seat height, back-rest incline, pin position…). During a workout you can adjust these and update this default.")
                ) {
                    Toggle("Machine-based", isOn: $machineEnabled.animation())

                    if machineEnabled {
                        MachineSettingsEditor(settings: $machineSettings)
                    }
                }

            }
            .sheet(isPresented: $showingExercisePicker) {
                ExercisePickerView { exerciseNames in
                    let picked = exerciseNames.first ?? "Unnamed"
                    exerciseName = picked
                    libraryName = picked
                }
            }
            .navigationTitle(exerciseName.isEmpty ? "New Exercise" : exerciseName)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") {
                        dismiss()
                    }
                }

                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Save") {
                        saveExercise()
                        dismiss()
                    }
                }
            }
        }
    }

    private func saveExercise() {
        let newWeight = weightTens + weightOnes
        let durationSecs = minutes * 60 + seconds

        // An emptied name falls back to the library exercise (or, failing that, the
        // prior name) rather than saving a blank display name.
        let trimmedName = exerciseName.trimmingCharacters(in: .whitespacesAndNewlines)
        let finalName = trimmedName.isEmpty ? (libraryName ?? exercise.name) : trimmedName

        var doc = RoutineDocument(from: routine)
        if let idx = doc.exercises.firstIndex(where: { $0.id == exercise.id }) {
            doc.exercises[idx].name = finalName
            // nil when the name matches the library exercise (unrenamed) — keeps an
            // unrenamed exercise byte-identical on disk.
            doc.exercises[idx].libraryName = (libraryName == finalName) ? nil : libraryName
            doc.exercises[idx].sets = sets
            doc.exercises[idx].reps = reps
            doc.exercises[idx].weight = Double(newWeight)
            doc.exercises[idx].loadType = loadType.rawValue
            doc.exercises[idx].durationSeconds = durationSecs
            // ON → a (possibly empty) array; OFF → nil, discarding any prior settings.
            doc.exercises[idx].machineSettings = machineEnabled ? machineSettings : nil
        }
        doc.updatedAt = Date()
        Task { await sync.save(routine: doc) }
    }
}
