module WorkflowStepController
  extend ActiveSupport::Concern

  included do
    helper_method :record_class
    helper_method :workflow_instance_class
    before_action :set_record, only: [:edit, :update, :destroy]
  end

  def edit
  end

  def record_class
    @record_class ||= self.class.name.sub(/Controller$/, '').split('::').map(&:singularize).join('::').constantize
  end

  def workflow_instance_class
    @workflow_instance_class ||= "WorkflowInstance::#{self.class.name.split('::').last.sub(/Controller$/, '').singularize}".constantize
  end

  # PATCH/PUT /owner_decommission/migrate_line_onnet_without_cpes/1
  def update
    authorize! :update, record_class
    @record.assign_attributes(record_params)
    if @record.valid?
      @record.public_send "#{record_commit_action}!"
      redirect_to polymorphic_path([@record.workflow_instance])
    else
      render :edit
    end
  end

  def destroy

  end

  # GET /contractor_completion/parallel_onnet_nls1_with_cpes/collection_edit
  def collection_edit
    authorize! :edit, record_class
    if params[:workflow_instance_ids].present?
      params[:workflow_instance_ids] = params[:workflow_instance_ids].split(RecordCollection.ids_separator) if params[:workflow_instance_ids].is_a?(String)
      @collection = record_class.collection.includes(:workflow_instance).joins(:workflow_instance).where(workflow_instances: {id: params[:workflow_instance_ids]})
    elsif params[:workflow_instance_batch_id].present?
      @workflow_instance_batch = WorkflowInstanceBatch.find(params[:workflow_instance_batch_id])
      @collection = record_class.collection.includes(:workflow_instance).joins(:workflow_instance)
        .where(workflow_instances: {workflow_instance_batch_id: @workflow_instance_batch.id})
        .where.not(workflow_instances: {state: 'any_rejected'})
        .refine_relation{ with_last_attribute_changes }
    else
      @collection = record_class.collection.includes(:workflow_instance).find(ids_param)
    end
    render layout: params[:reveal] != 'yes'
  end

  # GET /contractor_completion/parallel_onnet_nls1_with_cpes/collection_edit
  def collection_update
    authorize! :update, record_class
    @collection = record_class.collection.find(ids_param) # automatic security of find on specific sti class

    # Batch reject security
    if params[:workflow_instance_batch_id].present? and record_commit_action == 'reject'
      return redirect_to :back, alert: "You cannot reject an entire batch"
    end

    #TODO: the following code could be much nicer!
    if @collection.trigger_action!(record_commit_action, params[:collection])
      if params[:workflow_instance_batch_id].present?
        @workflow_instance_batch = WorkflowInstanceBatch.find(params[:workflow_instance_batch_id])
        redirect_to @workflow_instance_batch
      elsif @collection.one?
        redirect_to @collection.first.workflow_instance
      else
        redirect_to polymorphic_path([:selection, workflow_instance_class],  ids: @collection.map(&:workflow_instance_id).join(RecordCollection.ids_separator))
      end
    else
      render :collection_edit
    end
  end

  private


  # Translate the form commit action to a consistent useable and safe
  # processable name
  def record_commit_action
    case params[:commit]
    when t('workflow_step.process_button') then 'process'
    when t('workflow_step.complete_button') then 'complete'
    when t('workflow_step.reject_button') then 'reject'
    else raise "Unsupported record commit type given: #{params[:commit]}"
    end
  end

  # Use callbacks to share common setup or constraints between actions.
  def set_record
    @record = record_class.find(params[:id])
  end

  def record_params
    record_param = record_class.name.underscore.gsub('/', '_')
    return {} unless params[record_param].present? # Allow empty params, empty form just triggering state change is also an option
    #params.require( record_param ).permit( *permitted_attributes )
    params.require( record_param ).permit! #TODO: make secure!!!
  end

end

