module IDRAC::Lifecycle

def clear_lifecycle!

Clear the Lifecycle log
def clear_lifecycle!
  path = '/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellLCService/Actions/DellLCService.SystemErase'
  payload = { "Component": ["LCData"] }
  
  response = authenticated_request(
    :post, 
    path, 
    body: payload.to_json, 
    headers: { 'Content-Type' => 'application/json' }
  )
  
  if response.status.between?(200, 299)
    debug "Lifecycle log cleared", 0, :green
    return true
  else
    debug "Failed to clear Lifecycle log", 0, :red
    
    error_message = "Failed to clear Lifecycle log. Status code: #{response.status}"
    
    begin
      error_data = JSON.parse(response.body)
      error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
    rescue
      # Ignore JSON parsing errors
    end
    
    raise Error, error_message
  end
end

def clear_system_event_logs!

Clear the system event logs
def clear_system_event_logs!
  path = '/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Sel/Actions/LogService.ClearLog'
  
  response = authenticated_request(:post, path, body: {}.to_json, headers: { 'Content-Type' => 'application/json' })
  
  if response.status.between?(200, 299)
    debug "System Event Logs cleared", 0, :green
    return true
  else
    debug "Failed to clear System Event Logs", 0, :red
    
    error_message = "Failed to clear System Event Logs. Status code: #{response.status}"
    
    begin
      error_data = JSON.parse(response.body)
      error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
    rescue
      # Ignore JSON parsing errors
    end
    
    raise Error, error_message
  end
end

def ensure_lifecycle_controller!

Ensure the Lifecycle Controller is enabled
def ensure_lifecycle_controller!
  if !get_lifecycle_status
    debug "Lifecycle Controller is disabled, enabling...".yellow, 1
    set_lifecycle_status(true)
    
    # Verify it was enabled
    if !get_lifecycle_status
      raise Error, "Failed to enable Lifecycle Controller"
    end
    
    debug "Lifecycle Controller successfully enabled".green, 1
  else
    debug "Lifecycle Controller is already enabled".green, 1
  end
  
  return true
end

def get_lifecycle_status

True or False if it's enabled or not
They can do more than just the lifecycle, but that's what we need right now.
This follows from these Scripts "GetIdracLcSystemAttributesREDFISH.py" and "SetIdracLcSystemAttributesREDFISH.py"
def get_lifecycle_status
  # Check iDRAC version first to determine the right approach
  idrac_version = get_idrac_version rescue 0
  
  debug "Detected iDRAC version: #{idrac_version}", 1
  
  # Use version-specific methods
  if idrac_version > 9
    debug "Using modern approach for iDRAC > 9", 1
    return get_lifecycle_status_modern_firmware
  elsif idrac_version == 9
    debug "Using registry approach for iDRAC 9", 1
    return get_lifecycle_status_from_registry
  else
    debug "Using SCP approach for older iDRAC (v#{idrac_version})", 1
    return get_lifecycle_status_from_scp
  end
end

def get_lifecycle_status_from_registry

Get lifecycle status from registry (for iDRAC 9)
def get_lifecycle_status_from_registry
  # This big JSON explains all the attributes:
  path = "/redfish/v1/Registries/ManagerAttributeRegistry/ManagerAttributeRegistry.v1_0_0.json"
  response = authenticated_request(:get, path)
  if response.status != 200
    debug "Failed to get any Lifecycle Controller Attributes".red, 1
    return false
  end
  attributes = JSON.parse(response.body)
  # This is the attribute we want:
  target = attributes&.dig('RegistryEntries', 'Attributes')&.find {|q| q['AttributeName'] =~ /LCAttributes.1.LifecycleControllerState/ }
  # This is the FQDN of the attribute we want to get the value of:
  fqdn = target.dig('Id')  # LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState
  # This is the Current Value:
  response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellAttributes/#{fqdn}")
  if response.status != 200
    debug "Failed to get Lifecycle Controller Attributes".red, 1
    return false
  end
  attributes = JSON.parse(response.body)
  # There is a ValueName and a Value Display Name (e.g. Enabled, Disabled, Recovery)
  display = attributes&.dig('Attributes','LCAttributes.1.LifecycleControllerState')
  value = target&.dig('Value')&.find { |v| v['ValueDisplayName'] == display }&.dig('ValueName')&.to_i
  value == 1
end

def get_lifecycle_status_from_scp

Get lifecycle status from SCP export (for older iDRAC firmware)
def get_lifecycle_status_from_scp
  debug "Exporting System Configuration Profile to check LifecycleController state...", 1
  
  begin
    # Use the SCP export to get LifecycleController state
    scp = get_system_configuration_profile(target: "LifecycleController")
    
    # Check if we have data in the expected format
    if scp && scp["SystemConfiguration"] && scp["SystemConfiguration"]["Components"]
      # Find the LifecycleController component
      lc_component = scp["SystemConfiguration"]["Components"].find do |component|
        component["FQDD"] == "LifecycleController.Embedded.1"
      end
      
      if lc_component && lc_component["Attributes"]
        # Find the LifecycleControllerState attribute
        lc_state_attr = lc_component["Attributes"].find do |attr|
          attr["Name"] == "LCAttributes.1#LifecycleControllerState"
        end
        
        if lc_state_attr
          debug "Found LifecycleController state from SCP: #{lc_state_attr["Value"]}", 1
          return lc_state_attr["Value"] == "Enabled"
        end
      end
    end
    
    debug "Could not find LifecycleController state in SCP export", 1, :yellow
    return false
  rescue => e
    debug "Error getting Lifecycle Controller status from SCP: #{e.message}", 1, :red
    debug e.backtrace.join("\n"), 3, :red
    return false
  end
end

def get_lifecycle_status_modern_firmware

Check if the Lifecycle Controller is enabled
def get_lifecycle_status_modern_firmware
  # Try the standard Attributes endpoint first
  path = "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes"
  response = authenticated_request(:get, path)
  
  if response.status == 200
    begin
      attributes_data = JSON.parse(response.body)
      if attributes_data["Attributes"] && attributes_data["Attributes"]["LCAttributes.1.LifecycleControllerState"]
        lifecycle_state = attributes_data["Attributes"]["LCAttributes.1.LifecycleControllerState"]
        debug "Lifecycle Controller state (from Attributes): #{lifecycle_state}".light_cyan, 1
        return lifecycle_state == "Enabled"
      end
    rescue JSON::ParserError
      debug "Failed to parse Attributes response".yellow, 1
      # Fall through to registry method if parsing fails or attribute not found
    end
  else
    debug "Failed to get Attributes endpoint (Status: #{response.status}), trying registry method...".yellow, 1
  end
  
  # Try getting the DellAttributes for LifecycleController directly
  # The key insight is that we need to use just the base path without the fragment
  attributes_path = "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellAttributes/LifecycleController.Embedded.1"
  attributes_response = authenticated_request(:get, attributes_path)
  
  if attributes_response.status == 200
    begin
      dell_attr_data = JSON.parse(attributes_response.body)
      if dell_attr_data["Attributes"] && dell_attr_data["Attributes"]["LCAttributes.1.LifecycleControllerState"]
        lifecycle_state = dell_attr_data["Attributes"]["LCAttributes.1.LifecycleControllerState"]
        debug "Lifecycle Controller state (from Dell Attributes): #{lifecycle_state}".light_cyan, 1
        return lifecycle_state == "Enabled"
      end
    rescue JSON::ParserError
      debug "Failed to parse Dell Attributes response".yellow, 1
      # Fall through to registry method if parsing fails or attribute not found
    end
  else
    debug "Failed to get Dell Attributes (Status: #{attributes_response.status}), trying registry method...".yellow, 1
  end
  
  # Fallback to the registry method if both Attributes endpoints fail
  registry_response = authenticated_request(
    :get,
    "/redfish/v1/Registries/ManagerAttributeRegistry/ManagerAttributeRegistry.v1_0_0.json"
  )
  
  if registry_response.status != 200                                                                                               
    debug "Failed to get Lifecycle Controller Attributes Registry", 0, :red                                                             
    return false                                                                                                         
  end
  
  begin
    registry_data = JSON.parse(registry_response.body)
    # This is the attribute we want:                                                                                       
    target = registry_data['RegistryEntries']['Attributes'].find {|q| q['AttributeName'] =~ /LCAttributes.1.LifecycleControllerState/ }
    if !target
      debug "Could not find LCAttributes.1.LifecycleControllerState in registry", 0, :red
      return false
    end
    
    debug "Found attribute in registry but couldn't access it via other endpoints".yellow, 1
    return false
  rescue JSON::ParserError, NoMethodError, StandardError => e
    debug "Error during registry access: #{e.message}", 0, :red
    return false
  end
end

def get_system_event_logs

Get the system event logs
def get_system_event_logs
  path = '/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Sel?$expand=*($levels=1)'
  
  response = authenticated_request(:get, path)
  
  if response.status == 200
    begin
      data = JSON.parse(response.body)['Members'].map do |entry|
          { 
            id: entry['Id'],
            created: entry['Created'],
            message: entry['Message'],
            severity: entry['Severity']
          }
        end
      return data # RecursiveOpenStruct.new(data, recurse_over_arrays: true)
    rescue JSON::ParserError
      raise Error, "Failed to parse system event logs response: #{response.body}"
    end
  else
    raise Error, "Failed to get system event logs. Status code: #{response.status}"
  end
end

def set_lifecycle_status(status)

Set the Lifecycle Controller status (enable/disable)
def set_lifecycle_status(status)                                                                                   
  payload = { "Attributes": { "LCAttributes.1.LifecycleControllerState": status ? 'Enabled' : 'Disabled' } }
  response = authenticated_request(
    :patch,
    "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellAttributes/LifecycleController.Embedded.1",
    body: payload.to_json,
    headers: { 'Content-Type': 'application/json' }
  )
  
  code = response.status
  case code
  when 200..299
    debug "Lifecycle Controller is now #{status ? 'Enabled' : 'Disabled'}".green, 1                                          
  when 400..499
    debug "[#{code}] This iDRAC does not support Lifecycle Controller", 0, :red                                                
  when 500..599
    debug "[#{code}] iDRAC does not support Lifecycle Controller", 0, :red                                                     
  else
  end
end

def update_status_message(status)

Updates the status message for the lifecycle controller
def update_status_message(status)
  debug "Lifecycle Controller is now #{status ? 'Enabled' : 'Disabled'}".green, 1
end