class SvelteOnRails::Configuration

def self.instance

def self.instance
  @instance ||= new
end

def client_dist_folder(app_root = nil)

def client_dist_folder(app_root = nil)
  if Rails.env.development?
    rails_root(app_root).join('public', 'vite')
  else
    rails_root(app_root).join('public', 'vite')
  end
end

def components_folder

def components_folder
  Pathname.new(@configs[:components_folder].to_s)
end

def components_folder_full

def components_folder_full
  Pathname.new(frontend_folder_full).join(components_folder.to_s)
end

def frontend_folder

def frontend_folder
  Pathname.new(@configs[:frontend_folder].to_s)
end

def frontend_folder_full

def frontend_folder_full
  rails_root.join(@configs[:frontend_folder].to_s)
end

def initialize

def initialize
  @configs = redis_cache_store_configs
  return unless defined?(Rails.root)
  config_path = Rails.root.join("config", "svelte_on_rails.yml")
  return unless File.exist?(config_path)
  environments = Dir[Rails.root.join('config', 'environments', '*.rb')]
                   .map { |file| File.basename(file, '.rb') }
  configs_base = YAML.load_file(config_path)
  @configs = @configs.deep_merge(configs_base.reject { |k, _| environments.include?(k) })
  @configs = @configs.deep_merge(configs_base[Rails.env] || {})
  @configs = @configs.symbolize_keys
  if @configs[:redis_cache_store]
    if @configs[:redis_cache_store]['expires_in'].is_a?(String)
      @configs[:redis_cache_store]['expires_in'] = parse_duration(
        @configs[:redis_cache_store]['expires_in']
      )
    end
  end
  if defined? Redis
    @redis_instance = Redis.new(url: redis_cache_store[:url])
  end
end

def node_bin_path

def node_bin_path
  @node_bin_path ||= begin
                       n = ENV['SVELTE_ON_RAILS_NODE_BIN'] || 'node'
                       if n == 'node'
                         nvm_installed = false
                         nvm_dir = ENV['NVM_DIR'] || File.expand_path('~/.nvm')
                         nvm_installed ||= File.exist?("#{nvm_dir}/nvm.sh")
                         if nvm_installed
                           # Check for .nvmrc in the project root
                           project_root = rails_root || Dir.pwd
                           nvmrc_path = File.join(project_root, '.nvmrc')
                           use_nvmrc = File.exist?(nvmrc_path)
                           if use_nvmrc
                             # Read the version from .nvmrc
                             node_version = File.read(nvmrc_path).strip
                             # Ensure NVM is sourced and use the version from .nvmrc
                             command = "[ -s \"#{nvm_dir}/nvm.sh\" ] && . \"#{nvm_dir}/nvm.sh\" && nvm use #{node_version} > /dev/null 2>&1 && nvm which #{node_version}"
                           else
                             # Fallback to current NVM version
                             command = "[ -s \"#{nvm_dir}/nvm.sh\" ] && . \"#{nvm_dir}/nvm.sh\" && nvm which current"
                           end
                           node_path, status = Open3.capture2("bash -lc '#{command}'")
                           # Only update n if the command succeeded and output is non-empty
                           n = node_path.strip if status.success? && !node_path.strip.empty?
                         end
                       end
                       # Validate node_bin
                       unless n && !n.empty? && system("#{n} --version > /dev/null 2>&1")
                         raise "Node.js not found at '#{n || 'unknown'}'. Please configure SVELTE_ON_RAILS_NODE_BIN (e.g., to ~/.nvm/versions/node/vX.Y.Z/bin/node) or ensure 'node' is in the PATH. If using NVM, run `nvm alias default <version>` to set a default version or ensure a valid .nvmrc file is present."
                       end
                       n
                     rescue StandardError => e
                       raise "Failed to detect Node.js binary: «#{e.message}». Ensure Node.js is installed and accessible, or set SVELTE_ON_RAILS_NODE_BIN. If using .nvmrc, ensure the specified version is installed via NVM."
                     end
end

def non_ssr_request_header

def non_ssr_request_header
  rss = @configs[:non_ssr_request_header]
  if rss.present?
    rss
  else
    'X-Turbo-Request-ID'
  end
end

def parse_duration(string)

def parse_duration(string)
  # Extract number and unit
  match = string.match(/^(\d+)\.(\w+)$/)
  raise ArgumentError, "Invalid duration format: #{string}" unless match
  number, unit = match[1].to_i, match[2]
  # Ensure the unit is a valid ActiveSupport duration method
  valid_units = %w[seconds minutes hours days weeks months years]
  raise ArgumentError, "Invalid unit: #{unit} (valid: #{valid_units})" unless valid_units.include?(unit)
  ActiveSupport::Duration.build(number.send(unit))
end

def rails_root(root_url = nil)

def rails_root(root_url = nil)
  root_url || Rails.root
end

def redis_cache_store

def redis_cache_store
  (@configs[:redis_cache_store] || {}).transform_keys(&:to_sym)
end

def redis_cache_store_configs

def redis_cache_store_configs
  if defined?(Rails.application) && Rails.application.config.cache_store.is_a?(Array) && Rails.application.config.cache_store.first == :redis_cache_store
    { 'redis_cache_store' => Rails.application.config.cache_store.second.stringify_keys }
  else
    {}
  end
end

def redis_instance

def redis_instance
  @redis_instance
end

def ssr

def ssr
  rss = @configs[:ssr]
  if rss == false || rss == :auto
    rss
  else
    true
  end
end

def ssr_dist_folder(app_root = nil)

def ssr_dist_folder(app_root = nil)
  rails_root(app_root).join('public', 'vite-ssr')
end

def ssr_manifest

def ssr_manifest
  file = rails_root.join('public', 'vite-ssr', 'manifest.json')
  if watch_changes?
    begin
      JSON.parse(File.read(file))
    rescue
      raise "ERROR: Could not read public/vite-ssr/manifest.json."
    end
  else
    @manifest ||= JSON.parse(File.read(file))
  end
end

def system_type

def system_type
  :vite_rails
end

def watch_changes?

def watch_changes?
  @configs[:watch_changes] == true
end