# frozen_string_literal: true

module Gambiarra
  class App
    attr_reader :router, :debugging

    class << self
      attr_reader :app_class

      def inherited(app_class)
        @app_class = app_class
      end
    end

    def self.start(initial_route='')
      path, params = initial_route.split(' ').each_with_object([nil, {}]) do |segment, memo|
        if segment =~ /:/
          key, value = segment.split(':')
          memo[1].merge!([[key.to_sym, value.gsub('-', ' ')]].to_h)
        else
          memo[0] = [memo[0], segment].compact.join(' ')
        end
      end

      response = {path: (path || ''), **params}
      loop { response = app.flow(**response) }
    end

    def self.app
      @app ||= new
    end

    def initialize(debugging: false)
      debugging = true
      setup if respond_to?(:setup)
      @debugging = debugging
      @router = Router.new
    end

    def ask_questions(questions)
      questions.map { |name, question| [name, ask_question(question)] }.to_h
    end

    def ask_question(question)
      CLI::UI::Prompt.ask(question[:statement], options: question[:options])
    end

    def navigation(params)
      return {} if params.empty?
      CLI::UI::Prompt.ask('What to do now?') do |h|
        params.each do |key, _value|
          h.option("Different #{key}") { params[key] = nil }
        end
        h.option("Go back") { params[:path] = '' }
      end
      params
    end

    def output(response)
      return unless response[:content]
      puts [
        nil,
        "-> #{app_name} #{router.url}",
        nil,
        response[:content],
        nil
      ]
    end

    def app_name
      self.class.to_s.split('::').first.underscore.gsub('_', '-')
    end

    def flow(response)
      raise 'Response is empty' unless response
      output(response)
      response.delete(:content)
      questions = response&.delete(:questions) || {}
      response.merge!(navigation(response)) unless response.has_key?(:path) || questions.any?
      response.merge!(ask_questions(questions)) if questions.any?
      exit if response[:path] == 'exit'
      router.get(**response.compact)
    rescue => e
      puts e.backtrace if debugging
      puts e
      response.delete(:path)
      retry unless debugging
    end

    def exit
      Kernel.exit(0)
    end
  end
end