class ProductsReturnsController < ApplicationController
  before_action :set_products_return, only: [:show, :edit, :update, :destroy]

  ##--- Abilities
  load_and_authorize_resource

  ##--- Breadcrum_rails
  add_breadcrumb I18n.t("breadcrumbs." + controller_name), :products_returns_path
  add_breadcrumb "Nueva devolución", :new_products_return_path, only: :new
  add_breadcrumb "Detalle de la devolución", :products_return_path, only: :show

  # GET /products_returns
  # GET /products_returns.json
  def index
    @products_returns = current_user.usertype == 'A' ? ProductsReturn.all.includes(:sale, :user, :pointsale) : Pointsale.find(current_user.pointsale_id).products_returns.includes(:sale, :user).order(" products_returns.id DESC ")
  end

  # GET /products_returns/1
  # GET /products_returns/1.json
  def show; end

  # GET /products_returns/new
  def new
    @products_return = ProductsReturn.new
  end

  # GET /products_returns/1/edit
  def edit; end

  # POST /products_returns
  # POST /products_returns.json
  # rubocop:disable Metrics/BlockLength
  # rubocop:disable Metrics/BlockNesting
  def create
    respond_to do |format|
      @products_return = ProductsReturn.new
      @products_return.sale_id = params[:sale_id]
      @products_return.user_id = current_user.id
      @products_return.return_code = "#{current_user.pointsale.prefix}-D-#{ProductsReturn.where(pointsale_id: current_user.pointsale_id).count.next}"
      @products_return.pointsale_id = current_user.pointsale_id
      @products_return.new_amount = params[:new_amount]
      @products_return.returned_amount = params[:returned_amount]
      @products_return.difference_amount = params[:difference_amount]

      @products_return.audit_comment = "devolución #{@products_return.return_code} creada."
      if @products_return.save
        @products_in = JSON.parse params[:products_in]
        @products_out = JSON.parse params[:products_out]

        @products_in.each do |obj|
          detail = ProductsReturnIn.new
          detail.product_id = obj['product_id']
          detail.quantity = obj['quantity']
          detail.reason = obj['reason']
          detail.is_wasted = obj['is_wasted']
          detail.amount = obj['amount']
          @products_return.products_return_ins << detail

          if detail.is_wasted?
            product_waste = ProductWaste.new
            product_waste.product_id = detail.product_id
            product_waste.quantity = detail.quantity
            product_waste.reason = "devolución #{@products_return.return_code}"
            product_waste.status = :active
            product_waste.user_id = current_user.id
            product_waste.pointsale_id = @products_return.pointsale_id
            product_waste.products_return_in_id = detail.id
            product_waste.save
          else
            available_product = AvailableProduct.find_by(product_id: detail.product_id, pointsale_id: @products_return.pointsale_id)
            if available_product.present?
              available_product.stock = 0 if available_product.stock.blank?
              available_product.stock += detail.quantity
            else
              available_product = AvailableProduct.new
              available_product.product_id = detail.product_id
              available_product.pointsale_id = @products_return.pointsale_id
              available_product.stock = detail.quantity
            end
            available_product.save
          end
        end

        @products_out.each do |obj|
          detail = ProductsReturnOut.new
          detail.product_id = obj['product_id']
          detail.quantity = obj['quantity']
          detail.amount = obj['amount']
          @products_return.products_return_outs << detail

          available_product = AvailableProduct.find_by(product_id: detail.product_id, pointsale_id: @products_return.pointsale_id)
          unless available_product.blank?
            available_product.stock -= detail.quantity
            available_product.save
          end
        end

        if @products_return.difference_amount > 0
          format.js { redirect_to new_cash_registers_move_path(products_return: @products_return.id) }
        else
          format.js { flash[:success] = "Devolución creada correctamente." }
        end
        format.json { render :show, status: :created, location: @products_return }
      else
        format.js
        format.json { render json: @products_return.errors, status: :unprocessable_entity }
      end
    end
  end
  # rubocop:enable Metrics/BlockLength
  # rubocop:enable Metrics/BlockNesting

  # PATCH/PUT /products_returns/1
  # PATCH/PUT /products_returns/1.json
  def update
    respond_to do |format|
      if @products_return.update(products_return_params)
        format.html { redirect_to @products_return, notice: 'Products return was successfully updated.' }
        format.json { render :show, status: :ok, location: @products_return }
      else
        format.html { render :edit }
        format.json { render json: @products_return.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /products_returns/1
  # DELETE /products_returns/1.json
  def destroy
    @products_return.destroy
    respond_to do |format|
      format.html { redirect_to products_returns_url, notice: 'Products return was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def get_sale_details
    respond_to do |format|
      @details = Sale.find(params[:sale_id]).sales_details
      format.js
    end
  end

  def check_sale_detail_quantity
    detail = SalesDetail.find(params[:sale_detail_id])
    render json: detail.quantity
  end

  def add_product_to_return
    @product_for_return = Product.find(params[:product_id])
    @sale = Sale.find(params[:sale_id])
    @object_totals = get_totals
  end

  def update_quantity_prod_return
    @stock = AvailableProduct.find_by(pointsale_id: current_user.pointsale_id, product_id: params[:product_id])
    @product_for_return = Product.find(params[:product_id])
    @sale = Sale.find(params[:sale_id])
    @object_totals = params[:quantity].to_i <= @stock.stock ? get_totals : nil
    render json: @object_totals
  end

  def add_haggle
    respond_to do |format|
      @product_for_return = Product.find(params[:product_id])
      @sale = Sale.find(params[:sale_id])
      @object_totals = get_totals
      @suggested_haggle = (@pos_config.haggle_in_sale_percent.to_f / 100) * (@object_totals['total'])
      format.js
    end
  end

  def create_haggle
    respond_to do |format|
      @product_for_return = Product.find(params[:product_id])
      @sale = Sale.find(params[:sale_id])
      @haggle_percent = params[:haggle_percent].present? ? params[:haggle_percent].to_f : nil
      @haggle_quantity = params[:haggle_quantity].present? ? params[:haggle_quantity].to_f : nil
      @object_totals = get_totals

      format.js
    end
  end

  def print_receipt
    respond_to do |format|
      products_return = ProductsReturn.find(params[:products_return_id])
      pointsale = products_return.sale.get_pointsale

      format.pdf do
        render pdf: "ticket_devolucion_#{products_return.id}", template: "products_returns/receipt.pdf.erb", layout: 'receipt.html.erb', locals: { products_return: products_return, pointsale: pointsale }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
      end
    end
  end

  private

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

  def get_totals
    if @product_for_return.present? && @sale.present?
      obj = Hash.new

      obj['quantity'] = params[:quantity].present? ? params[:quantity] : 1

      obj['unit_price'] = @product_for_return.get_price_sale(current_user.pointsale_id)

      obj['discount'] = 0.0
      special_price = SpecialPrice.find_by(customer_id: @sale.customer_id, product_id: @product_for_return.id)
      unless special_price.blank?
        discount_per_unit = special_price.get_unit_discount(obj['unit_price'])
        obj['discount'] = discount_per_unit * obj['quantity'].to_i
      end

      obj['amount'] = obj['quantity'].to_i * obj['unit_price']

      obj['tax'] = 0.0

      if @product_for_return.include_sale_tax == 1
        obj['tax'] = ((PosConfig.first.tax_percent / 100) * obj['amount']).round(2)
      end

      obj['total'] = (obj['amount'] - obj['discount']) + obj['tax']

      haggle = 0.0
      if @haggle_percent.present?
        haggle = (@haggle_percent / 100) * obj['total']
      elsif @haggle_quantity.present?
        haggle = @haggle_quantity
      end

      obj['discount'] += haggle
      obj['total'] = (obj['amount'] - obj['discount']) + obj['tax']

      obj
    end
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def products_return_params
    params[:products_return]
  end
end
