module SvelteOnRails::Installer::Npm

def self.inspect_package(package_name)

def self.inspect_package(package_name)
  pkg = nil
  version = nil
  if File.exist?('package-lock.json')
    pl = JSON.parse(File.read('package-lock.json'))
    unless pl['packages']
      raise "ERROR: package-lock.json found, but no packages found, seems to be corrupted."
    end
    pkg = pl['packages'].keys.grep(/\/#{package_name}$/).first
    version = pl['packages'][pkg]['version'] if pkg
  end
  if pkg
    {
      type: pkg.match(/^.*?(?=\/[^\/]*$)/).to_s,
      version: version&.split('.')&.map(&:to_i)
    }
  end
end

def self.install_or_update_package(package_name, minimal_version: nil, major_version: nil, update_to_latest: true, dev_dependency: false)

def self.install_or_update_package(package_name, minimal_version: nil, major_version: nil, update_to_latest: true, dev_dependency: false)
  pkg = inspect_package(package_name)
  puts "#{package_name} already installed (#{pkg[:version].join('.')})" if pkg
  to_do = if !pkg
            true
          elsif major_version
            r = pkg[:version].first != major_version
            if r
              puts "updating to major version #{major_version}"
            else
              puts "nothing to do (major version #{major_version} OK)"
            end
            r
          elsif minimal_version
            r = pkg[:version].first < minimal_version.first || pkg[:version].second < minimal_version.second
            puts "updating to minimal version #{minimal_version}" if r
            r
          else
            puts 'nothing to do'
            false
          end
  save_dev = (dev_dependency ? ' --save-dev' : '')
  if to_do
    cmd = if major_version
            "npm install #{package_name}@#{major_version}#{save_dev}"
          elsif update_to_latest
            "npm install #{package_name}@latest#{save_dev}"
          else
            raise "ERROR: not implemented"
          end
    stdout, stderr, status = Open3.capture3(cmd)
    puts cmd
    if stderr.present?
      raise "ERROR #{cmd} => #{stderr}"
    end
    notice = [
      (pkg ? "Updated" : "Installed"),
      package_name,
      (pkg ? "from version #{pkg[:version].join('.')}" : nil),
      (pkg ? "to" : nil),
      "@latest"
    ].compact.join(' ')
    puts notice
  else
    min_str = minimal_version.present? ? ", required: >= #{minimal_version.join('.')}" : ''
    puts "#{package_name} already installed (#{pkg[:version].join('.')}#{min_str}), skipping."
  end
end

def self.link_local_package(package_name, local_package_url)

def self.link_local_package(package_name, local_package_url)
  Dir.chdir(local_package_url) do
    `npm unlink`
    `npm link`
  end
  Dir.chdir(Rails.root) do
    # Instead of just `npm link`, use `npm install` to add the local package to package.json
    `npm install #{local_package_url} --save`
    stdout, stderr, status = Open3.capture3("npm ls #{package_name}")
    if stderr.present?
      raise "ERROR: npm link failed for #{package_name} => #{stderr}"
    end
    puts "Successfully linked #{package_name} to #{local_package_url}"
    puts "  • `npm ls #{package_name}` => «#{stdout}»"
  end
end