//
//  AddFuelLogView.swift
//  Gas Man
//
//  Created by Kameron Kenny on 3/17/25.
//

import SwiftUI
import CoreData

// Helper function to check if a string is properly formatted (e.g., "18.526")
func isProperlyFormatted(_ input: String) -> Bool {
    let pattern = #"^\d+\.\d{3}$"#
    return input.range(of: pattern, options: .regularExpression) != nil
}

// helper function to format input.
func formatInput(_ input: String) -> String {
    // Extract only numeric characters.
    let digitsOnly = input.filter { $0.isNumber }
    // If no digits, return empty.
    guard !digitsOnly.isEmpty else { return "" }
    // Convert to an integer to remove any leading zeros.
    let numberValue = Int(digitsOnly) ?? 0
    // Convert back to a string.
    let digits = String(numberValue)
    
    if digits.count > 3 {
        // Insert decimal point so that the last 3 digits are decimals.
        let integerPart = digits.dropLast(3)
        let decimalPart = digits.suffix(3)
        return "\(integerPart).\(decimalPart)"
    } else {
        // If fewer than 4 digits, pad with zeros on the left to 3 digits.
        let padded = String(repeating: "0", count: 3 - digits.count) + digits
        return "0." + padded
    }
}

struct AddFuelLogView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @Environment(\.dismiss) var dismiss

    // Form fields for fuel log
    @State private var date = Date()
    @State private var odometer = ""
    @State private var fuelVolume: String = ""
    @State private var cost = ""
    @State private var locationCoordinates = ""
    @State private var locationName = ""
    @State private var selectedOctane: Int = 87  // Default or from previous record
    @State private var pricePerGalon = ""
    // New Full Tank toggle; default is on (true)
    @State private var fullTank: Bool = true
    
    // Allowed octane options
    let octaneOptions = [87, 89, 91, 92, 93, 95]
    
    // Location manager for automatic location updates
    @StateObject private var locationManager = LocationManager()
    
    // For tracking the previous odometer reading
    @State private var previousOdometer: Double? = nil
    @State private var showOdometerAlert = false
    @State private var isUpdatingCalculation = false
    
    // Vehicle selection:
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Vehicle.make, ascending: true)],
        animation: .default)
    private var vehicles: FetchedResults<Vehicle>
    
    // Use the new UUID id for vehicle selection
    @State private var selectedVehicleID: UUID? = nil
    
    // Computed property for formatted previous odometer value
    private var previousOdometerString: String {
        previousOdometer.map { String(format: "%.0f", $0) } ?? "N/A"
    }
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Fuel Log Details")) {
                    DatePicker("Date", selection: $date, displayedComponents: [.date, .hourAndMinute])
                    
                    HStack {
                        Text("Odometer:")
                        TextField("", text: $odometer)
                            .keyboardType(.decimalPad)
                            .multilineTextAlignment(.trailing)
                    }
                    
                    HStack {
                        Text("Gallons:")
                        TextField("", text: $fuelVolume)
                            .keyboardType(.decimalPad)
                            .multilineTextAlignment(.trailing)
                            .onChange(of: fuelVolume) { newValue in
                                // Only reformat if the input is not already in the proper format.
//                                if newValue.contains(".") { return }
                                let pattern = #"^\d+\.\d{3}$"#
                                if newValue.range(of: pattern, options: .regularExpression) != nil {
                                    return
                                }
                                let formatted = formatInput(newValue)
                                if formatted != newValue {
                                    fuelVolume = formatted
                                }
                                updateCalculatedValues()
                            }
                    }
                    
                    HStack {
                        Text("Price/Gal:")
                        TextField("", text: $pricePerGalon)
                            .keyboardType(.decimalPad)
                            .multilineTextAlignment(.trailing)
                            .onChange(of: pricePerGalon) { newValue in
//                                if newValue.contains(".") { return }
                                let pattern = #"^\d+\.\d{3}$"#
                                if newValue.range(of: pattern, options: .regularExpression) != nil {
                                    return
                                }
                                let formatted = formatInput(newValue)
                                if formatted != newValue {
                                    pricePerGalon = formatted
                                }
                                updateCalculatedValues()
                            }
                    }
                    
                    HStack {
                        Text("Cost:")
                        TextField("", text: $cost)
                            .keyboardType(.decimalPad)
                            .multilineTextAlignment(.trailing)
                            .onChange(of: cost) { _ in updateCalculatedValues() }
                    }
                    
                    // New Full Tank toggle
                    Toggle("Full Tank", isOn: $fullTank)
                        .toggleStyle(SwitchToggleStyle(tint: .blue))
                    
                    Button("Get Current Location") {
                        locationManager.requestLocation()
                    }
                    
                    if !locationCoordinates.isEmpty {
                        Text("Coordinates: \(locationCoordinates)")
                    }
                    
                    TextField("Location Name", text: $locationName)
                        .multilineTextAlignment(.trailing)
                    
                    Picker("Octane", selection: $selectedOctane) {
                        ForEach(octaneOptions, id: \.self) { option in
                            Text("\(option)").tag(option)
                        }
                    }
                    .pickerStyle(MenuPickerStyle())
                }
                
                Section(header: Text("Vehicle")) {
                    Picker("Select Vehicle", selection: $selectedVehicleID) {
                        ForEach(vehicles, id: \.id) { vehicle in
                            Text("\(vehicle.year ?? "") \(vehicle.make ?? "") \(vehicle.model ?? "")")
                                .tag(vehicle.id)
                        }
                    }
                    .pickerStyle(MenuPickerStyle())
                }
            }
            .navigationTitle("Add Fuel Log")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Save") { saveFuelLog() }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") { dismiss() }
                }
            }
            .onChange(of: locationManager.location) { newLocation in
                if let loc = newLocation {
                    locationCoordinates = "\(loc.coordinate.latitude), \(loc.coordinate.longitude)"
                }
            }
            .onChange(of: locationManager.placemark) { newPlacemark in
                if let placemark = newPlacemark {
                    locationName = placemark.name ?? ""
                }
            }
            .onAppear {
                // Fetch the last FuelLog record to set defaults:
                let fetchRequest: NSFetchRequest<FuelLog> = FuelLog.fetchRequest()
                fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
                fetchRequest.fetchLimit = 1
                if let lastFuelLog = try? viewContext.fetch(fetchRequest).first {
                    selectedOctane = Int(lastFuelLog.octane)
                    previousOdometer = lastFuelLog.odometer
                    odometer = String(format: "%.0f", lastFuelLog.odometer)
                    
                    // Set default vehicle from previous record if available:
                    if let lastVehicle = lastFuelLog.vehicle {
                        selectedVehicleID = lastVehicle.id
                    }
                } else {
                    selectedOctane = 87
                    odometer = ""
                    // If no previous fuel log, default to the first available vehicle.
                    selectedVehicleID = vehicles.first?.id
                }
            }
            .alert(isPresented: $showOdometerAlert) {
                Alert(title: Text("Odometer Reading Error"),
                      message: Text("Odometer reading must be greater than the previous record (\(previousOdometerString))."),
                      dismissButton: .default(Text("OK")))
            }
        }
    }
    
    private func roundToThree(_ value: Double) -> Double {
        return (value * 1000).rounded() / 1000
    }
    
    private func roundToTwo(_ value: Double) -> Double {
        return (value * 100).rounded() / 100
    }
    
    private func updateCalculatedValues() {
        guard !isUpdatingCalculation else { return }
        isUpdatingCalculation = true
        
        let fuel = Double(fuelVolume)
        let costVal = Double(cost)
        let price = Double(pricePerGalon)
        
        if let f = fuel, let p = price, f > 0 {
            let computedCost = roundToTwo(f * p)
            let computedCostStr = String(format: "%.2f", computedCost)
            if cost != computedCostStr {
                cost = computedCostStr
            }
        } else if let f = fuel, let c = costVal, f > 0, pricePerGalon.trimmingCharacters(in: .whitespaces).isEmpty {
            let computedPrice = roundToThree(c / f)
            let computedPriceStr = String(format: "%.3f", computedPrice)
            if pricePerGalon != computedPriceStr {
                pricePerGalon = computedPriceStr
            }
        } else if let p = price, let c = costVal, p > 0, fuelVolume.trimmingCharacters(in: .whitespaces).isEmpty {
            let computedFuel = roundToThree(c / p)
            let computedFuelStr = String(format: "%.3f", computedFuel)
            if fuelVolume != computedFuelStr {
                fuelVolume = computedFuelStr
            }
        }
        
        isUpdatingCalculation = false
    }
    
    private func saveFuelLog() {
        guard let newOdometer = Double(odometer) else { return }
        
        // Re-fetch the latest fuel log from Core Data
        let fetchRequest: NSFetchRequest<FuelLog> = FuelLog.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
        fetchRequest.fetchLimit = 1
        if let lastFuelLog = try? viewContext.fetch(fetchRequest).first {
            if newOdometer <= lastFuelLog.odometer {
                showOdometerAlert = true
                return
            }
        }
        
        let newLog = FuelLog(context: viewContext)
        newLog.id = UUID()
        newLog.date = date
        newLog.odometer = newOdometer
        newLog.fuelVolume = Double(fuelVolume) ?? 0
        newLog.cost = Double(cost) ?? 0
        newLog.locationCoordinates = locationCoordinates
        newLog.locationName = locationName
        newLog.octane = Int16(selectedOctane)
        newLog.pricePerGalon = Double(pricePerGalon) ?? 0
        // Set the fullTank property from the toggle:
        newLog.fullTank = fullTank
        
        if let vehicleID = selectedVehicleID,
           let selectedVehicle = vehicles.first(where: { $0.id == vehicleID }) {
            newLog.vehicle = selectedVehicle
        }
        
        do {
            try viewContext.save()
            print("Saved fuel log with vehicle: \(newLog.vehicle?.make ?? "none")")
            dismiss()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
    }
}
