import CoreData
import SwiftUI
import Swinject

extension Adjustments {
    struct RootView: BaseView {
        let resolver: Resolver
        @State var state = StateModel()
        @State private var isEditing = false
        @State private var showOverrideCreationSheet = false
        @State private var showTempTargetCreationSheet = false
        @State private var showingDetail = false
        @State private var showCheckmark: Bool = false
        @State private var selectedPresetID: String?
        @State private var selectedTempTargetPresetID: String?
        @State private var selectedOverride: OverrideStored?
        @State private var selectedTempTarget: TempTargetStored?
        @State private var isConfirmDeletePresented = false
        @State private var isPromptPresented = false
        @State private var isRemoveAlertPresented = false
        @State private var removeAlert: Alert?
        @State private var isEditingTT = false

        @Environment(\.colorScheme) var colorScheme
        @Environment(AppState.self) var appState

        private func formattedGlucose(glucose: Decimal) -> String {
            let formattedValue: String
            if state.units == .mgdL {
                formattedValue = Formatter.glucoseFormatter(for: state.units)
                    .string(from: glucose as NSDecimalNumber) ?? "\(glucose)"
            } else {
                formattedValue = glucose.formattedAsMmolL
            }
            return "\(formattedValue) \(state.units.rawValue)"
        }

        var body: some View {
            ZStack(alignment: .center, content: {
                VStack {
                    Picker("Adjustment Tabs", selection: $state.selectedTab) {
                        ForEach(Adjustments.Tab.allCases.indexed(), id: \.1) { index, item in
                            Text(item.name).tag(index)
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                    .padding(.horizontal)

                    List {
                        switch state.selectedTab {
                        case .overrides: overrides()
                        case .tempTargets: tempTargets() }
                    }
                    .scrollContentBackground(.hidden)
                    .background(appState.trioBackgroundColor(for: colorScheme))
                }
                .listSectionSpacing(10)
                .safeAreaInset(edge: .bottom, spacing: 30) { stickyStopButton }
                .scrollContentBackground(.hidden)
                .background(appState.trioBackgroundColor(for: colorScheme))
                .onAppear(perform: configureView)
                .navigationBarTitle("Adjustments")
                .navigationBarTitleDisplayMode(.large)
                .toolbar {
                    ToolbarItem(placement: .topBarTrailing) {
                        switch state.selectedTab {
                        case .overrides:
                            Button(action: {
                                showOverrideCreationSheet = true
                            }, label: {
                                HStack {
                                    Text("Add Override")
                                    Image(systemName: "plus")
                                }
                            })
                        case .tempTargets:
                            Button(action: {
                                showTempTargetCreationSheet = true
                            }, label: {
                                HStack {
                                    Text("Add Temp Target")
                                    Image(systemName: "plus")
                                }
                            })
                        }
                    }
                }
                .sheet(isPresented: $state.showOverrideEditSheet, onDismiss: {
                    Task {
                        await state.resetStateVariables()
                        state.showOverrideEditSheet = false
                    }

                }) {
                    if let override = selectedOverride {
                        EditOverrideForm(overrideToEdit: override, state: state)
                    }
                }
                .sheet(isPresented: $showOverrideCreationSheet, onDismiss: {
                    Task {
                        await state.resetStateVariables()
                        showOverrideCreationSheet = false
                    }
                }) {
                    AddOverrideForm(state: state)
                }
                .sheet(isPresented: $showTempTargetCreationSheet, onDismiss: {
                    Task {
                        await state.resetTempTargetState()
                        showTempTargetCreationSheet = false
                    }
                }) {
                    AddTempTargetForm(state: state)
                }
                .sheet(isPresented: $state.showTempTargetEditSheet, onDismiss: {
                    Task {
                        await state.resetTempTargetState()
                        state.showTempTargetEditSheet = false
                    }

                }) {
                    if let tempTarget = selectedTempTarget {
                        EditTempTargetForm(tempTargetToEdit: tempTarget, state: state)
                    }
                }
            }).background(appState.trioBackgroundColor(for: colorScheme))
        }

        @ViewBuilder func overrides() -> some View {
            if state.isEnabled, state.activeOverrideName.isNotEmpty {
                currentActiveAdjustment
            }
            if state.overridePresets.isNotEmpty {
                overridePresets
            } else {
                defaultText
            }
        }

        @ViewBuilder func tempTargets() -> some View {
            if state.isTempTargetEnabled, state.activeTempTargetName.isNotEmpty {
                currentActiveAdjustment
            }
            if state.scheduledTempTargets.isNotEmpty {
                scheduledTempTargets
            }
            if state.tempTargetPresets.isNotEmpty {
                tempTargetPresets
            } else {
                defaultText
            }
        }

        private var defaultText: some View {
            switch state.selectedTab {
            case .overrides:
                Section {} header: {
                    Text("Add Preset or Override by tapping 'Add Override +' in the top right-hand corner of the screen.")
                        .textCase(nil)
                        .foregroundStyle(.secondary)
                }
            case .tempTargets:
                Section {} header: {
                    Text(
                        "Add Preset or Temp Target by tapping 'Add Temp Target +' in the top right-hand corner of the screen."
                    )
                    .textCase(nil)
                    .foregroundStyle(.secondary)
                }
            }
        }

        private var overridePresets: some View {
            Section {
                ForEach(state.overridePresets) { preset in
                    overridesView(for: preset)
                        .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                            Button(role: .none) {
                                selectedOverride = preset
                                isConfirmDeletePresented = true
                            } label: {
                                Label("Delete", systemImage: "trash")
                                    .tint(.red)
                            }
                            Button(action: {
                                // Set the selected Override to the chosen Preset and pass it to the Edit Sheet
                                selectedOverride = preset
                                state.showOverrideEditSheet = true
                            }, label: {
                                Label("Edit", systemImage: "pencil")
                                    .tint(.blue)
                            })
                        }
                }
                .onMove(perform: state.reorderOverride)
                .confirmationDialog(
                    "Delete the Override Preset \"\(selectedOverride?.name ?? "")\"?",
                    isPresented: $isConfirmDeletePresented,
                    titleVisibility: .visible
                ) {
                    if let itemToDelete = selectedOverride {
                        Button(
                            state.currentActiveOverride == selectedOverride ? "Stop and Delete" : "Delete",
                            role: .destructive
                        ) {
                            if state.currentActiveOverride == selectedOverride {
                                Task {
                                    // Save cancelled Override in OverrideRunStored Entity
                                    // Cancel ALL active Override
                                    await state.disableAllActiveOverrides(createOverrideRunEntry: true)
                                }
                            }
                            // Perform the delete action
                            Task {
                                await state.invokeOverridePresetDeletion(itemToDelete.objectID)
                            }
                            // Reset the selected item after deletion
                            selectedOverride = nil
                        }
                    }
                    Button("Cancel", role: .cancel) {
                        // Dismiss the dialog without action
                        selectedOverride = nil
                    }
                } message: {
                    if state.currentActiveOverride == selectedOverride {
                        Text(
                            state
                                .currentActiveOverride == selectedOverride ?
                                "This override preset is currently running. Deleting will stop it." : ""
                        )
                    }
                }
                .listRowBackground(Color.chart)
            } header: {
                Text("Override Presets")
            } footer: {
                HStack {
                    Image(systemName: "hand.draw.fill").foregroundStyle(.primary)
                    Text("Swipe left to edit or delete an override preset. Hold, drag and drop to reorder a preset.")
                }
            }
        }

        private var scheduledTempTargets: some View {
            Section {
                ForEach(state.scheduledTempTargets) { tempTarget in
                    tempTargetView(for: tempTarget)
                        .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                            swipeActions(for: tempTarget)
                        }
                }
                .listRowBackground(Color.chart)
            } header: {
                Text("Scheduled Temp Targets")
            }
        }

        private var tempTargetPresets: some View {
            Section {
                ForEach(state.tempTargetPresets) { preset in
                    tempTargetView(for: preset, showCheckmark: showCheckmark) {
                        enactTempTargetPreset(preset)
                    }
                    .swipeActions(edge: .trailing, allowsFullSwipe: true) {
                        swipeActions(for: preset)
                    }
                }
                .onMove(perform: state.reorderTempTargets)
                .confirmationDialog(
                    deleteConfirmationTitle,
                    isPresented: $isConfirmDeletePresented,
                    titleVisibility: .visible
                ) {
                    deleteConfirmationButtons()
                } message: {
                    deleteConfirmationMessage
                }
                .listRowBackground(Color.chart)
            } header: {
                Text("Temporary Target Presets")
            } footer: {
                HStack {
                    Image(systemName: "hand.draw.fill").foregroundStyle(.primary)
                    Text("Swipe left to edit or delete a temporary target preset. Hold, drag and drop to reorder a preset.")
                }
            }
        }

        private func enactTempTargetPreset(_ preset: TempTargetStored) {
            Task {
                let objectID = preset.objectID
                await state.enactTempTargetPreset(withID: objectID)
                selectedTempTargetPresetID = preset.id?.uuidString
                showCheckmark.toggle()

                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    showCheckmark = false
                }
            }
        }

        private func swipeActions(for tempTarget: TempTargetStored) -> some View {
            Group {
                Button {
                    Task {
                        selectedTempTarget = tempTarget
                        isConfirmDeletePresented = true
                    }
                } label: {
                    Label("Delete", systemImage: "trash")
                        .tint(.red)
                }
                Button(action: {
                    selectedTempTarget = tempTarget
                    state.showTempTargetEditSheet = true
                }, label: {
                    Label("Edit", systemImage: "pencil")
                        .tint(.blue)
                })
            }
        }

        private var deleteConfirmationTitle: String {
            "Delete the Temp Target Preset \"\(selectedTempTarget?.name ?? "")\"?"
        }

        private func deleteConfirmationButtons() -> some View {
            Group {
                if let itemToDelete = selectedTempTarget {
                    Button(
                        state.currentActiveTempTarget == selectedTempTarget ? "Stop and Delete" : "Delete",
                        role: .destructive
                    ) {
                        if state.currentActiveTempTarget == selectedTempTarget {
                            Task {
                                await state.disableAllActiveTempTargets(createTempTargetRunEntry: true)
                            }
                        }
                        Task {
                            await state.invokeTempTargetPresetDeletion(itemToDelete.objectID)
                        }
                        selectedTempTarget = nil
                    }
                }
                Button("Cancel", role: .cancel) {
                    selectedTempTarget = nil
                }
            }
        }

        private var deleteConfirmationMessage: Text? {
            if state.currentActiveTempTarget == selectedTempTarget {
                return Text("This Temp Target preset is currently running. Deleting will stop it.")
            }
            return nil
        }

        private var currentActiveAdjustment: some View {
            switch state.selectedTab {
            case .overrides:
                Section {
                    HStack {
                        Text("\(state.activeOverrideName) is running")

                        Spacer()
                        Image(systemName: "square.and.pencil")
                            .foregroundStyle(Color.primary)
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        Task {
                            /// To avoid editing the Preset when a Preset-Override is running we first duplicate the Preset-Override as a non-Preset Override
                            /// The currentActiveOverride variable in the State will update automatically via MOC notification
                            await state.duplicateOverridePresetAndCancelPreviousOverride()

                            /// selectedOverride is used for passing the chosen Override to the EditSheet so we have to set the updated currentActiveOverride to be the selectedOverride
                            selectedOverride = state.currentActiveOverride

                            /// Now we can show the Edit sheet
                            state.showOverrideEditSheet = true
                        }
                    }
                }
                .listRowBackground(Color.purple.opacity(0.8))
            case .tempTargets:
                Section {
                    HStack {
                        Text("\(state.activeTempTargetName) is running")

                        Spacer()
                        Image(systemName: "square.and.pencil")
                            .foregroundStyle(Color.primary)
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        Task {
                            /// To avoid editing the Preset when a Preset-Override is running we first duplicate the Preset-Override as a non-Preset Override
                            /// The currentActiveOverride variable in the State will update automatically via MOC notification
                            await state.duplicateTempTargetPresetAndCancelPreviousTempTarget()

                            /// selectedOverride is used for passing the chosen Override to the EditSheet so we have to set the updated currentActiveOverride to be the selectedOverride
                            selectedTempTarget = state.currentActiveTempTarget

                            /// Now we can show the Edit sheet
                            state.showTempTargetEditSheet = true
                        }
                    }
                }
                .listRowBackground(Color.loopGreen.opacity(0.8))
            }
        }

        var stickyStopButton: some View {
            ZStack {
                Rectangle()
                    .frame(width: UIScreen.main.bounds.width, height: 65)
                    .foregroundStyle(colorScheme == .dark ? Color.bgDarkerDarkBlue : Color.white)
                    .background(.thinMaterial)
                    .opacity(0.8)
                    .clipShape(Rectangle())

                Group {
                    switch state.selectedTab {
                    case .overrides:
                        Button(action: {
                            Task {
                                // Save cancelled Override in OverrideRunStored Entity
                                // Cancel ALL active Override
                                await state.disableAllActiveOverrides(createOverrideRunEntry: true)
                            }
                        }, label: {
                            Text("Stop Override")
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                                .padding(10)
                        })
                            .frame(width: UIScreen.main.bounds.width * 0.9, height: 40, alignment: .center)
                            .disabled(!state.isEnabled)
                            .background(!state.isEnabled ? Color(.systemGray4) : Color(.systemRed))
                            .tint(.white)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                    case .tempTargets:
                        Button(action: {
                            Task {
                                // Save cancelled Temp Targets in TempTargetRunStored Entity
                                // Cancel ALL active Temp Targets
                                await state.disableAllActiveTempTargets(createTempTargetRunEntry: true)
                                // Update View
                                state.updateLatestTempTargetConfiguration()
                            }
                        }, label: {
                            Text("Stop Temp Target")
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                                .padding(10)
                        })
                            .frame(width: UIScreen.main.bounds.width * 0.9, height: 40, alignment: .center)
                            .disabled(!state.isTempTargetEnabled)
                            .background(!state.isTempTargetEnabled ? Color(.systemGray4) : Color(.systemRed))
                            .tint(.white)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                    }
                }
                .padding(5)
            }
        }

        private var cancelAdjustmentButton: some View {
            switch state.selectedTab {
            case .overrides:
                Button(action: {
                    Task {
                        // Save cancelled Override in OverrideRunStored Entity
                        // Cancel ALL active Override
                        await state.disableAllActiveOverrides(createOverrideRunEntry: true)
                    }
                }, label: {
                    Text("Stop Override")

                })
                    .frame(maxWidth: .infinity, alignment: .center)
                    .disabled(!state.isEnabled)
                    .listRowBackground(!state.isEnabled ? Color(.systemGray4) : Color(.systemRed))
                    .tint(.white)
            case .tempTargets:
                Button(action: {
                    Task {
                        // Save cancelled Temp Targets in TempTargetRunStored Entity
                        // Cancel ALL active Temp Targets
                        await state.disableAllActiveTempTargets(createTempTargetRunEntry: true)

                        // Update View
                        state.updateLatestTempTargetConfiguration()
                    }
                }, label: {
                    Text("Stop Temp Target")

                })
                    .frame(maxWidth: .infinity, alignment: .center)
                    .disabled(!state.isTempTargetEnabled)
                    .listRowBackground(!state.isTempTargetEnabled ? Color(.systemGray4) : Color(.systemRed))
                    .tint(.white)
            }
        }

        private func tempTargetView(
            for tempTarget: TempTargetStored,
            showCheckmark: Bool = false,
            onTap: (() -> Void)? = nil
        ) -> some View {
            let target = tempTarget.target ?? 100
            let tempTargetValue = Decimal(target as! Double.RawValue)
            let isSelected = tempTarget.id?.uuidString == selectedPresetID
            let tempTargetHalfBasal = Decimal(
                tempTarget.halfBasalTarget as? Double
                    .RawValue ?? Double(state.settingHalfBasalTarget)
            )
            let percentage = Int(
                state.computeAdjustedPercentage(usingHBT: tempTargetHalfBasal, usingTarget: tempTargetValue)
            )
            let remainingTime = tempTarget.date?.timeIntervalSinceNow ?? 0

            return ZStack(alignment: .trailing) {
                HStack {
                    VStack(alignment: .leading) {
                        HStack {
                            Text(tempTarget.name ?? "")
                            Spacer()
                            if remainingTime > 0 {
                                Text("Starts in \(formattedTimeRemaining(remainingTime))")
                                    .foregroundColor(colorScheme == .dark ? .orange : .accentColor)
                            }
                        }
                        HStack(spacing: 2) {
                            Text(formattedGlucose(glucose: target as Decimal))
                                .foregroundColor(.secondary)
                                .font(.caption)
                            Text("for")
                                .foregroundColor(.secondary)
                                .font(.caption)
                            Text("\(Formatter.integerFormatter.string(from: (tempTarget.duration ?? 0) as NSNumber)!)")
                                .foregroundColor(.secondary)
                                .font(.caption)
                            Text("min")
                                .foregroundColor(.secondary)
                                .font(.caption)
                            if state.isAdjustSensEnabled(usingTarget: tempTargetValue) {
                                Text(", \(percentage)%")
                                    .foregroundColor(.secondary)
                                    .font(.caption)
                            }
                            Spacer()
                        }
                        .padding(.top, 2)
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        onTap?()
                    }
                }
                if showCheckmark && isSelected {
                    Image(systemName: "checkmark.circle.fill")
                        .imageScale(.large)
                        .fontWeight(.bold)
                        .foregroundStyle(Color.green)
                } else if onTap != nil {
                    Image(systemName: "line.3.horizontal")
                        .imageScale(.medium)
                        .foregroundStyle(.secondary)
                }
            }
        }

        private func formattedTimeRemaining(_ timeInterval: TimeInterval) -> String {
            let totalSeconds = Int(timeInterval)
            let hours = totalSeconds / 3600
            let minutes = (totalSeconds % 3600) / 60
            let seconds = totalSeconds % 60

            if hours > 0 {
                return "\(hours)h \(minutes)m \(seconds)s"
            } else if minutes > 0 {
                return "\(minutes)m \(seconds)s"
            } else {
                return "<1m"
            }
        }

        private var overrideLabelDivider: some View {
            Divider()
                .frame(width: 1, height: 20)
        }

        @ViewBuilder private func overridesView(for preset: OverrideStored) -> some View {
            let isSelected = preset.id == selectedPresetID
            let name = preset.name ?? ""
            let indefinite = preset.indefinite
            let duration = preset.duration?.decimalValue ?? Decimal(0)
            let percentage = preset.percentage
            let smbMinutes = preset.smbMinutes?.decimalValue ?? Decimal(0)
            let uamMinutes = preset.uamMinutes?.decimalValue ?? Decimal(0)

            let target: String = {
                guard let targetValue = preset.target, targetValue != 0 else { return "" }
                return state.units == .mgdL ? targetValue.description : targetValue.decimalValue.formattedAsMmolL
            }()

            let targetString = target.isEmpty ? "" : "\(target) \(state.units.rawValue)"

            let durationString = indefinite ? "" : "\(state.formatHrMin(Int(duration)))"

            let scheduledSMBString: String = {
                guard preset.smbIsScheduledOff, preset.start != preset.end else { return "" }
                return " \(formatTimeRange(start: preset.start?.stringValue, end: preset.end?.stringValue))"
            }()

            let smbString: String = {
                guard preset.smbIsOff || preset.smbIsScheduledOff else { return "" }
                return "SMBs Off\(scheduledSMBString)"
            }()

            let maxSmbMinsString: String = {
                guard smbMinutes != 0, preset.advancedSettings, !preset.smbIsOff,
                      smbMinutes != state.defaultSmbMinutes else { return "" }
                return "\(smbMinutes.formatted()) min SMB"
            }()

            let maxUamMinsString: String = {
                guard uamMinutes != 0, preset.advancedSettings, !preset.smbIsOff,
                      uamMinutes != state.defaultUamMinutes else { return "" }
                return "\(uamMinutes.formatted()) min UAM"
            }()

            let isfAndCrString: String = {
                switch (preset.isfAndCr, preset.isf, preset.cr) {
                case (_, true, true),
                     (true, _, _):
                    return " ISF/CR"
                case (false, true, false):
                    return " ISF"
                case (false, false, true):
                    return " CR"
                default:
                    return ""
                }
            }()

            let percentageString = percentage != 100 ? "\(Int(percentage))%\(isfAndCrString)" : ""

            // Combine all labels into a single array, filtering out empty strings
            let labels: [String] = [
                durationString,
                percentageString,
                targetString,
                smbString,
                maxSmbMinsString,
                maxUamMinsString
            ].filter { !$0.isEmpty }

            if !name.isEmpty {
                ZStack(alignment: .trailing) {
                    HStack {
                        VStack {
                            HStack {
                                Text(name)
                                Spacer()
                            }
                            HStack(spacing: 5) {
                                ForEach(labels, id: \.self) { label in
                                    Text(label)
                                    if label != labels.last { // Add divider between labels
                                        overrideLabelDivider
                                    }
                                }
                                Spacer()
                            }
                            .padding(.top, 2)
                            .foregroundColor(.secondary)
                            .font(.caption)
                        }
                        .contentShape(Rectangle())
                        .onTapGesture {
                            Task {
                                let objectID = preset.objectID
                                await state.enactOverridePreset(withID: objectID)
                                state.hideModal()
                                showCheckmark.toggle()
                                selectedPresetID = preset.id

                                // Deactivate checkmark after 3 seconds
                                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                                    showCheckmark = false
                                }
                            }
                        }
                    }
                    // show checkmark to indicate if the preset was actually pressed
                    if showCheckmark && isSelected {
                        Image(systemName: "checkmark.circle.fill")
                            .imageScale(.large)
                            .fontWeight(.bold)
                            .foregroundStyle(Color.green)
                    } else {
                        Image(systemName: "line.3.horizontal")
                            .imageScale(.medium)
                            .foregroundStyle(.secondary)
                    }
                }
            }
        }
    }
}
