import Foundation
import SwiftUI

struct AddOverrideForm: View {
    @Environment(\.presentationMode) var presentationMode
    @StateObject var state: OverrideConfig.StateModel
    @State private var selectedIsfCrOption: isfAndOrCrOptions = .isfAndCr
    @State private var selectedDisableSmbOption: disableSmbOptions = .dontDisable
    @State private var displayPickerDuration: Bool = false
    @State private var displayPickerStart: Bool = false
    @State private var displayPickerEnd: Bool = false
    @State private var displayPickerSmbMinutes: Bool = false
    @State private var displayPickerUamMinutes: Bool = false
    @State private var durationHours = 0
    @State private var durationMinutes = 0
    @State private var overrideTarget = false
    @Environment(\.colorScheme) var colorScheme
    @State private var showAlert = false
    @State private var alertString = ""

    @Environment(\.dismiss) var dismiss

    enum isfAndOrCrOptions: String, CaseIterable {
        case isfAndCr = "ISF/CR"
        case isf = "ISF"
        case cr = "CR"
        case none = "None"
    }

    enum disableSmbOptions: String, CaseIterable {
        case dontDisable = "Don't Disable"
        case disable = "Disable"
        case disableOnSchedule = "Disable on Schedule"
    }

    var color: LinearGradient {
        colorScheme == .dark ? LinearGradient(
            gradient: Gradient(colors: [
                Color.bgDarkBlue,
                Color.bgDarkerDarkBlue
            ]),
            startPoint: .top,
            endPoint: .bottom
        )
            :
            LinearGradient(
                gradient: Gradient(colors: [Color.gray.opacity(0.1)]),
                startPoint: .top,
                endPoint: .bottom
            )
    }

    private var formatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 0
        return formatter
    }

    private var glucoseFormatter: NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 0
        if state.units == .mmolL {
            formatter.maximumFractionDigits = 1
        }
        formatter.roundingMode = .halfUp
        return formatter
    }

    private var alertMessage: String {
        let target: String = state.units == .mgdL ? "70-270 mg/dl" : "4-15 mmol/l"
        return "Please enter a valid target between" + " \(target)."
    }

    var body: some View {
        NavigationView {
            Form {
                addOverride()
            }.scrollContentBackground(.hidden).background(color)
                .navigationTitle("Add Override")
                .navigationBarItems(trailing: Button("Cancel") {
                    presentationMode.wrappedValue.dismiss()
                })
        }
    }

    @ViewBuilder private func addOverride() -> some View {
        Section {
            VStack {
                HStack {
                    Text("Name")
                    Spacer()
                    TextField("(Optional)", text: $state.overrideName).multilineTextAlignment(.trailing)
                }
            }

            VStack {
                HStack {
                    Spacer()

                    // Decrement button
                    Button(action: {
                        if state.overrideSliderPercentage > 10 {
                            state.overrideSliderPercentage -= 1
                        }
                    }) {
                        Image(systemName: "minus.circle.fill")
                            .font(.title)
                            .foregroundColor(state.overrideSliderPercentage > 10 ? .accentColor : .loopGray)
                    }
                    .buttonStyle(PlainButtonStyle())

                    Spacer()

                    Text("\(Int(state.overrideSliderPercentage)) %")
                        .font(.largeTitle)
                        .foregroundColor(.accentColor)

                    Spacer()

                    // Increment button
                    Button(action: {
                        if state.overrideSliderPercentage < 200 {
                            state.overrideSliderPercentage += 1
                        }
                    }) {
                        Image(systemName: "plus.circle.fill")
                            .font(.title)
                            .foregroundColor(state.overrideSliderPercentage < 200 ? .accentColor : .loopGray)
                    }
                    .buttonStyle(PlainButtonStyle())

                    Spacer()
                }
                .padding()

                // Slider to adjust value
                Slider(
                    value: $state.overrideSliderPercentage,
                    in: 10 ... 200,
                    step: 1
                )

                // Picker for ISF/CR settings
                Picker("Apply to", selection: $selectedIsfCrOption) {
                    ForEach(isfAndOrCrOptions.allCases, id: \.self) { option in
                        Text(option.rawValue).tag(option)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .onChange(of: selectedIsfCrOption) { newValue in
                    switch newValue {
                    case .isfAndCr:
                        state.isfAndCr = true
                        state.isf = true
                        state.cr = true
                    case .isf:
                        state.isfAndCr = false
                        state.isf = true
                        state.cr = false
                    case .cr:
                        state.isfAndCr = false
                        state.isf = false
                        state.cr = true
                    case .none:
                        state.isfAndCr = false
                        state.isf = false
                        state.cr = false
                    }
                }
            }

            VStack {
                Toggle(isOn: $state.indefinite) {
                    Text("Enable Indefinitely")
                }
                if !state.indefinite {
                    VStack {
                        HStack {
                            Text("Duration")
                            Spacer()
                            Text(formatHrMin(Int(state.overrideDuration)))
                                .foregroundColor(!displayPickerDuration ? .primary : .accentColor)
                        }
                        .onTapGesture {
                            displayPickerDuration.toggle()
                        }

                        if displayPickerDuration {
                            HStack {
                                Picker("Hours", selection: $durationHours) {
                                    ForEach(0 ..< 24) { hour in
                                        Text("\(hour) hr").tag(hour)
                                    }
                                }
                                .pickerStyle(WheelPickerStyle())
                                .frame(width: 100)
                                .onChange(of: durationHours) { _ in
                                    state.overrideDuration = Decimal(totalDurationInMinutes())
                                }

                                Picker("Minutes", selection: $durationMinutes) {
                                    ForEach(Array(stride(from: 0, through: 55, by: 5)), id: \.self) { minute in
                                        Text("\(minute) min").tag(minute)
                                    }
                                }
                                .pickerStyle(WheelPickerStyle())
                                .frame(width: 100)
                                .onChange(of: durationMinutes) { _ in
                                    state.overrideDuration = Decimal(totalDurationInMinutes())
                                }
                            }
                        }
                    }
                    .padding(.top)
                }
            }

            VStack {
                Toggle(isOn: $state.shouldOverrideTarget) {
                    Text("Override Profile Target")
                }
                if state.shouldOverrideTarget {
                    HStack {
                        Text("Target Glucose")
                        TextFieldWithToolBar(text: $state.target, placeholder: "0", numberFormatter: glucoseFormatter)
                        Text(state.units.rawValue).foregroundColor(.secondary)
                    }
                }
            }

            VStack {
                // Picker for ISF/CR settings
                Picker("Disable SMBs", selection: $selectedDisableSmbOption) {
                    ForEach(disableSmbOptions.allCases, id: \.self) { option in
                        Text(option.rawValue).tag(option)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .onChange(of: selectedDisableSmbOption) { newValue in
                    switch newValue {
                    case .dontDisable:
                        state.smbIsOff = false
                        state.smbIsScheduledOff = false
                    case .disable:
                        state.smbIsOff = true
                        state.smbIsScheduledOff = false
                    case .disableOnSchedule:
                        state.smbIsOff = false
                        state.smbIsScheduledOff = true
                    }
                }

                if state.smbIsScheduledOff {
                    // First Hour SMBs Are Disabled
                    VStack {
                        HStack {
                            Text("From")
                            Spacer()

                            Text(
                                is24HourFormat() ? format24Hour(Int(truncating: state.start as NSNumber)) + ":00" :
                                    convertTo12HourFormat(Int(truncating: state.start as NSNumber))
                            )
                            .foregroundColor(!displayPickerStart ? .primary : .accentColor)
                        }
                        .onTapGesture {
                            displayPickerStart.toggle()
                        }

                        if displayPickerStart {
                            Picker(selection: Binding(
                                get: { Int(truncating: state.start as NSNumber) },
                                set: { state.start = Decimal($0) }
                            ), label: Text("")) {
                                ForEach(0 ..< 24, id: \.self) { hour in
                                    Text(is24HourFormat() ? format24Hour(hour) + ":00" : convertTo12HourFormat(hour))
                                        .tag(hour)
                                }
                            }
                            .pickerStyle(WheelPickerStyle())
                            .frame(maxWidth: .infinity)
                        }
                    }
                    .padding(.top, 10)

                    // First Hour SMBs Are Resumed
                    VStack {
                        HStack {
                            Text("To")
                            Spacer()
                            Text(
                                is24HourFormat() ? format24Hour(Int(truncating: state.end as NSNumber)) + ":00" :
                                    convertTo12HourFormat(Int(truncating: state.end as NSNumber))
                            )
                            .foregroundColor(!displayPickerEnd ? .primary : .accentColor)
                        }
                        .onTapGesture {
                            displayPickerEnd.toggle()
                        }

                        if displayPickerEnd {
                            Picker(selection: Binding(
                                get: { Int(truncating: state.end as NSNumber) },
                                set: { state.end = Decimal($0) }
                            ), label: Text("")) {
                                ForEach(0 ..< 24, id: \.self) { hour in
                                    Text(is24HourFormat() ? format24Hour(hour) + ":00" : convertTo12HourFormat(hour))
                                        .tag(hour)
                                }
                            }
                            .pickerStyle(WheelPickerStyle())
                            .frame(maxWidth: .infinity)
                        }
                    }
                    .padding(.vertical, 10)
                }
            }

            if !state.smbIsOff {
                VStack {
                    Toggle(isOn: $state.advancedSettings) {
                        Text("Override Max SMB Minutes")
                    }

                    if state.advancedSettings {
                        // SMB Minutes Picker
                        VStack {
                            HStack {
                                Text("Max SMB Minutes")
                                Spacer()

                                Text("\(state.smbMinutes.formatted(.number)) min")
                                    .foregroundColor(!displayPickerSmbMinutes ? .primary : .accentColor)
                            }
                            .onTapGesture {
                                displayPickerSmbMinutes.toggle()
                            }

                            if displayPickerSmbMinutes {
                                Picker(selection: Binding(
                                    get: { Int(truncating: state.smbMinutes as NSNumber) },
                                    set: { state.smbMinutes = Decimal($0) }
                                ), label: Text("")) {
                                    ForEach(Array(stride(from: 0, through: 180, by: 5)), id: \.self) { minute in
                                        Text("\(minute) min").tag(minute)
                                    }
                                }
                                .pickerStyle(WheelPickerStyle())
                                .frame(maxWidth: .infinity)
                            }
                        }
                        .padding(.top)

                        // UAM SMB Minutes Picker
                        VStack {
                            HStack {
                                Text("Max UAM SMB Minutes")
                                Spacer()
                                Text("\(state.uamMinutes.formatted(.number)) min")
                                    .foregroundColor(!displayPickerUamMinutes ? .primary : .accentColor)
                            }
                            .onTapGesture {
                                displayPickerUamMinutes.toggle()
                            }

                            if displayPickerUamMinutes {
                                Picker(selection: Binding(
                                    get: { Int(truncating: state.uamMinutes as NSNumber) },
                                    set: { state.uamMinutes = Decimal($0) }
                                ), label: Text("")) {
                                    ForEach(Array(stride(from: 0, through: 180, by: 5)), id: \.self) { minute in
                                        Text("\(minute) min").tag(minute)
                                    }
                                }
                                .pickerStyle(WheelPickerStyle())
                                .frame(maxWidth: .infinity)
                            }
                        }
                        .padding(.top)
                    }
                }
            }

            startAndSaveProfiles
        }
        header: { Text("Add custom Override") }
        footer: {
            Text(
                "Your profile ISF and CR will be inversely adjusted with the override percentage."
            )
        }.listRowBackground(Color.chart)
    }

    private var startAndSaveProfiles: some View {
        HStack {
            Button("Start New Override") {
                if !state.isInputInvalid(target: state.target) {
                    showAlert.toggle()

                    alertString = "\(state.overrideSliderPercentage.formatted(.number)) %, " +
                        (
                            state.overrideDuration > 0 || !state
                                .indefinite ?
                                (
                                    state
                                        .overrideDuration
                                        .formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) +
                                        " min."
                                ) :
                                NSLocalizedString(" infinite duration.", comment: "")
                        ) +
                        (
                            (state.target == 0 || !state.shouldOverrideTarget) ? "" :
                                (" Target: " + state.target.formatted() + " " + state.units.rawValue + ".")
                        )
                        +
                        (
                            state
                                .smbIsOff ?
                                NSLocalizedString(
                                    " SMBs are disabled either by schedule or during the entire duration.",
                                    comment: ""
                                ) : ""
                        )
                        +
                        "\n\n"
                        +
                        NSLocalizedString(
                            "Starting this override will change your profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Override” will start your new Override or edit your current active Override.",
                            comment: ""
                        )
                }
            }
            .disabled(unChanged())
            .buttonStyle(BorderlessButtonStyle())
            .font(.callout)
            .controlSize(.mini)
            .alert(
                "Start Override",
                isPresented: $showAlert,
                actions: {
                    Button("Cancel", role: .cancel) { state.isEnabled = false }
                    Button("Start Override", role: .destructive) {
                        Task {
                            if state.indefinite { state.overrideDuration = 0 }
                            state.isEnabled.toggle()
                            await state.saveCustomOverride()
                            await state.resetStateVariables()
                            dismiss()
                        }
                    }
                },
                message: {
                    Text(alertString)
                }
            )
            .alert(isPresented: $state.showInvalidTargetAlert) {
                Alert(
                    title: Text("Invalid Input"),
                    message: Text("\(state.alertMessage)"),
                    dismissButton: .default(Text("OK")) { state.showInvalidTargetAlert = false }
                )
            }
            Button {
                Task {
                    if !state.isInputInvalid(target: state.target) {
                        await state.saveOverridePreset()
                        dismiss()
                    }
                }
            }
            label: { Text("Save as Preset") }
                .tint(.orange)
                .frame(maxWidth: .infinity, alignment: .trailing)
                .buttonStyle(BorderlessButtonStyle())
                .controlSize(.mini)
                .disabled(unChanged())
        }
    }

    private func totalDurationInMinutes() -> Int {
        let durationTotal = (durationHours * 60) + durationMinutes
        return max(0, durationTotal)
    }

    private func unChanged() -> Bool {
        let defaultProfile = state.overrideSliderPercentage == 100 && !state.shouldOverrideTarget && !state.advancedSettings
        let noDurationSpecified = !state.indefinite && state.overrideDuration == 0
        let targetZeroWithOverride = state.shouldOverrideTarget && state.target == 0
        let allSettingsDefault = state.overrideSliderPercentage == 100 && !state.shouldOverrideTarget && !state.smbIsOff && !state
            .smbIsScheduledOff && state.smbMinutes == state.defaultSmbMinutes && state.uamMinutes == state.defaultUamMinutes

        return defaultProfile || noDurationSpecified || targetZeroWithOverride || allSettingsDefault
    }
}

// Function to check if the phone is using 24-hour format
func is24HourFormat() -> Bool {
    let formatter = DateFormatter()
    formatter.locale = Locale.current
    formatter.dateStyle = .none
    formatter.timeStyle = .short
    let dateString = formatter.string(from: Date())

    return !dateString.contains("AM") && !dateString.contains("PM")
}

// Helper function to convert hours to AM/PM format
func convertTo12HourFormat(_ hour: Int) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "h a"

    // Create a date from the hour and format it to AM/PM
    let calendar = Calendar.current
    let components = DateComponents(hour: hour)
    let date = calendar.date(from: components) ?? Date()

    return formatter.string(from: date)
}

// Helper function to format 24-hour numbers as two digits
func format24Hour(_ hour: Int) -> String {
    String(format: "%02d", hour)
}

func formatHrMin(_ durationInMinutes: Int) -> String {
    let hours = durationInMinutes / 60
    let minutes = durationInMinutes % 60

    switch (hours, minutes) {
    case let (0, m):
        return "\(m) min"
    case let (h, 0):
        return "\(h) hr"
    default:
        return "\(hours) hr \(minutes) min"
    }
}
