module SvelteOnRails::Installer::Utils

def self.add_line_to_file(file_path, line)

def self.add_line_to_file(file_path, line)
  file_content = File.exist?(file_path) ? File.read(file_path) : ""
  if file_content.match?(/#{line}/)
    puts "#{line} already present in #{file_path}, nothing changed here."
    return
  end
  File.open(file_path, 'a') do |file|
    file.puts(line)
  end
  puts "added #{line} to #{file_path}."
rescue StandardError => e
  puts "Error: #{e.message}"
end

def self.add_route(route)

def self.add_route(route)
  file_path = 'config/routes.rb'
  # Read the file content
  content = File.read(file_path)
  # Split content into lines
  lines = content.lines
  # Find the index of Rails.application.routes.draw do
  ind = -1
  lines.each_with_index do |line, i|
    if line.match?(/^\s*Rails.application.routes.draw\s*do[\s\S]+$/)
      ind = i
    end
  end
  # Insert
  if ind >= 0
    lines.insert(ind + 1, route)
  else
    raise "ERROR: Could not find Rails.application.routes.draw do"
  end
  # Write the modified content back to the file
  begin
    File.write(file_path, lines.map { |l| l.gsub(/\n/, '') }.join("\n"))
    puts "Successfully inserted «root '#{route}'» into '#{file_path}'"
  rescue => e
    raise "Error writing to #{file_path} => «#{e.message}»"
  end
end

def self.ask_yn(question)

def self.ask_yn(question)
  begin
    puts "#{question} (y/n)"
    continue = STDIN.gets.chomp.downcase[0]
  end until ['y', 'n'].include?(continue)
  continue == 'y'
end

def self.check_file_exists(file_path)

def self.check_file_exists(file_path)
  unless File.exist?(file_path)
    raise "ERROR: File not found: #{file_path}"
  end
end

def self.check_file_not_exists(file_path)

def self.check_file_not_exists(file_path)
  if File.exist?(file_path)
    raise "ERROR: File already exists: #{file_path}"
  end
end

def self.check_folder_exists(folder_path)

def self.check_folder_exists(folder_path)
  unless File.exist?(folder_path)
    raise "ERROR: Folder not found: #{folder_path}"
  end
end

def self.check_folder_not_exists(folder_path)

def self.check_folder_not_exists(folder_path)
  if File.exist?(folder_path)
    raise "ERROR: Folder already exists: #{folder_path}"
  end
end

def self.create_file(file_path)

def self.create_file(file_path)
  unless File.exist?(file_path)
    FileUtils.touch(file_path)
    puts "Created empty file at file://#{file_path}"
  end
end

def self.create_folder(folder)

def self.create_folder(folder)
  if Dir.exist?(folder)
    puts "Folder already exists: #{folder}"
  else
    FileUtils.mkdir_p(folder)
    puts "Created folder: #{folder}"
  end
end

def self.create_javascript_initializer

def self.create_javascript_initializer
  config_path = Rails.root.join("app", "frontend", "initializers", "svelte.js")
  if File.exist?(config_path)
    puts "Initializer already exists: file://#{config_path}"
  else
    File.write(config_path, <<~JAVASCRIPT)
      import { initializeSvelteComponents, cleanupSvelteComponents } from '@csedl/svelte-on-rails';
      const components = import.meta.glob('/javascript/components/**/*.svelte', { eager: true });
      const componentsRoot = '/javascript/components';
      // Initialize Svelte components
      initializeSvelteComponents(componentsRoot, components, true);
      // Turbo event listener for page load
      document.addEventListener('turbo:load', () => {
          initializeSvelteComponents(componentsRoot, components, true);
      });
      // Turbo event listener for cleanup before page cache
      document.addEventListener('turbo:before-cache', () => {
          cleanupSvelteComponents(false);
      });
    JAVASCRIPT
    puts "Created initializer file at file://#{config_path}"
  end
end

def self.create_svelte_hello_world

def self.create_svelte_hello_world
  file_path = Rails.root.join("app", "frontend", "javascript", "components", "HelloWorld.svelte")
  if File.exist?(file_path)
    puts "Hello World file already exists: file://#{file_path}"
  else
    File.write(file_path, <<~HTML)
      <script>
          export let items
          let count = 0;
          function increment() {
              count += 1;
          }
      </script>
      <h1>Greetings from svelte</h1>
      <button on:click={increment}>Increment: {count}</button>
      <ul>
          {#each items as item}
              <li>{item}</li>
          {/each}
      </ul>
      <style>
          button {
              background-color: darkred;
              color: white;
              padding: 10px;
              border: none;
          }
      </style>
    HTML
    puts "Hello World file at file://#{file_path}"
  end
end

def self.install_npm_package

def self.install_npm_package
  package_name = "@csedl/svelte-on-rails@latest"
  puts "Installing #{package_name} via npm..."
  if system("npm install #{package_name}")
    puts "#{package_name} successfully installed."
  else
    abort "Failed to install #{package_name}. Please ensure npm is installed and try running 'npm install #{package_name}' manually."
  end
end

def self.install_turbo

def self.install_turbo
  pkg_js = Rails.root.join("package.json")
  package_name = "@hotwired/turbo-rails"
  file_content = File.exist?(pkg_js) ? File.read(pkg_js) : ""
  if file_content.match?(/#{package_name}/)
    puts "#{package_name} is already present in package.json, assuming that it is set up well and working."
  else
    puts "Installing #{package_name} via npm..."
    if system("npm install #{package_name}")
      puts "#{package_name} successfully installed."
      add_line_to_file(Rails.root.join("app", "frontend", "entrypoints", "application.js"), "import '#{package_name}';")
    else
      abort "Failed to install #{package_name}. Please ensure npm is installed and try running 'npm install #{package_name}' manually."
    end
  end
end

def self.remove_files(file_paths)

def self.remove_files(file_paths)
  file_paths.each do |f|
    if File.exist?(f)
      if File.directory?(f)
        Dir.delete(f)
        puts "  • Removed directory: #{f}"
      else
        File.delete(f)
        puts "  • Removed file: #{f}"
      end
    else
      puts "  • File/Path not found so not removed: #{f}"
    end
  end
end

def self.remove_line_from_file(file_path, string_to_find)

def self.remove_line_from_file(file_path, string_to_find)
  # Read the file content
  content = File.read(file_path)
  # Split content into lines
  lines = content.lines
  found_lines = []
  modified_content = []
  lines.each do |line|
    if line.match(/^[\s\S]+#{string_to_find}[\s\S]+$/)
      found_lines.push(line)
    else
      modified_content.push(line)
    end
  end
  utils = SvelteOnRails::Installer::Utils
  if found_lines.present? && utils.ask_yn("Remove lines\n#{found_lines.join("\n  • ")}\n from #{file_path}?")
    # Write the modified content back to the file
    begin
      File.write(file_path, modified_content.map{|l|l.gsub(/\n/, '')}.join("\n"))
      puts "Successfully removed #{found_lines.length} #{'line'.pluralize(found_lines.length)}."
    rescue => e
      raise "Error writing to #{file_path} => «#{e.message}»"
    end
  else
  end
end

def self.route_exists?(target_route)

def self.route_exists?(target_route)
  # check if exists
  # Ensure the Rails environment is loaded
  # require File.expand_path("../config/environment", __dir__)
  # Get all routes from the Rails application
  routes = Rails.application.routes.routes
  # Check if the route exists
  routes.any? do |route|
    # Extract the path spec and remove any optional parts or constraints
    path = route.path.spec.to_s
    # Clean up the path to match the format (remove leading/trailing slashes, etc.)
    cleaned_path = path.gsub(/\(.*\)/, "").gsub(/^\/|\/$/, "")
    # Check if the cleaned path matches the target route
    cleaned_path == target_route
  end
end

def self.run_command(command)

def self.run_command(command)
  Dir.chdir(Rails.root) do
    stdout, stderr, status = Open3.capture3(command)
    if stderr.present?
      puts "Error running command «#{command}»:"
      raise stderr
    else
      puts "#{command} => Success"
    end
  end
end

def self.which_root_route

def self.which_root_route
  # Check if the root route is active (uncommented) or commented out
  routes = File.read(Rails.root.join('config', 'routes.rb'))
  m = routes.match(/^\s*root\s+['"]([^'"]+)['"]/m)
  if m
    m.to_s.match(/^\s*root\s*['"]([^'"]*)['"]/)[1]
  end
end

def self.write_templates(template_paths)

def self.write_templates(template_paths)
  existing = template_paths.select { |p| File.exist?(p) }
  verb = 'Created'
  if existing.present?
    begin
      puts "#{'Template'.pluralize(existing.length)} already exists:\n#{existing.join("\n")}.\nOverwrite? (y/n)"
      continue = STDIN.gets.chomp.downcase[0]
    end until ['y', 'n'].include?(continue)
    if continue == 'n'
      puts "Skipping write #{'template'.pluralize(template_paths.length)}."
      return
    end
    verb = 'Overwrote'
  end
  template_paths.each do |p|
    source_path = File.expand_path('rails_template', __dir__) + '/' + p
    FileUtils.mkdir_p(File.dirname(p))
    FileUtils.cp(source_path, p)
  end
  puts "#{verb} #{'file'.pluralize(template_paths.length)}:\n#{template_paths.join("\n")}"
end