class ImprintableTrain < ActiveRecord::Base
  acts_as_paranoid

  include Softwear::Auth::BelongsToUser
  include PublicActivity::Model
  include Train

  SOLUTIONS = {
    need_to_order:           :ready_to_order,
    need_to_inventory:       :ordered,
    need_to_fully_inventory: :partially_inventoried,
  }
    .with_indifferent_access

  tracked only: [:transition]
  acts_as_warnable

  belongs_to :job
  belongs_to_user_called :inventoried_by
  belongs_to_user_called :staged_by
  has_one :order, through: :job
  has_many :imprints, through: :job

  searchable do
    text :job_name, :imprint_names, :location
    string :order_imprint_state do
      order.try(:imprint_state)
    end
    string :order_production_state do
      order.try(:production_state)
    end
    string :job_imprint_state do
      job.try(:imprint_state)
    end
    string :job_production_state do
      job.try(:production_state)
    end
    time(:expected_arrival_date) { |i| i.expected_arrival_date.try(:to_date) }
    time :created_at
    integer :job_id
    boolean :fba
  end

  attr_reader :solution
  attr_accessor :ordering_complete

  train_type :pre_production
  train initial: :ready_to_order, final: :inventoried do
    success_event :ordered, params: { expected_arrival_date: :date_field } do
      transition :ready_to_order => :ordered
    end

    success_event :partially_inventoried, params: { 
      location: :text_field,
      inventoried_by_id: -> { User.of_role("receiving").map{ |u| [u.full_name, u.id] } } } do
      transition [:ordered, :partially_inventoried, :staged] => :partially_inventoried
    end

    success_event :inventoried, params: { 
      location: :text_field, 
      inventoried_by_id: -> { User.of_role("receiving").map{ |u| [u.full_name, u.id] } } } do
      transition [:ordered, :partially_inventoried, :staged] => :inventoried
    end

    success_event :staged, params: { 
      location: :text_field,
      staged_by_id: -> { User.of_role("receiving").map{ |u| [u.full_name, u.id] } } } do
      transition [:staged, :ordered, :partially_inventoried, :inventoried] => :inventoried
    end

    success_event :resolved_changes, params: { solution: SOLUTIONS.keys.map { |k| [k.to_s.humanize, k] } } do
      SOLUTIONS.each do |solution, state|
        transition :imprintable_changed => state, if: ->(i) { i.solution == solution.to_sym }
      end
      transition :imprintable_changed => same
    end

    delay_event :imprintable_line_items_changed do
      transition all - :imprintable_changed => :imprintable_changed
    end

    success_event :reset_state_machine do
      transition [:partially_ordered] => :ready_to_order
    end

    success_event :moved_inventory, params: { location: :text_field } do
      transition :inventoried => :inventoried
    end

    state :imprintable_changed, type: :delay
    state :inventoried, type: :success
  end

  def self.find_scheduled_at(date)
    imprints = ImprintableTrain.joins(:imprints).where("imprints.scheduled_at like ?", "%#{date}%")
    groups   = ImprintGroup.where("scheduled_at like ?", "%#{date}%").flat_map{ |g| g.imprintable_trains }

    trains = imprints + groups
    return trains.uniq
  end

  def solution=(s)
    @solution = s.to_sym
  end

  def imprintable_train_status
    if state.include?("inventoried")
      "Location: #{location}"
    else
      "Expected arrival: #{expected_arrival_date.strftime("%a, %b %d, %Y") rescue "Not ordered yet"}"
    end  
  end

  private

  def job_name
    job.try(:name)
  end

  def imprint_names
    imprints.pluck(:name).join(' ')
  end

  def order_name
    job.try(:order).try(:name)
  end
end
