class ProductsController < ApplicationController
  ##--- Abilities
  load_and_authorize_resource

  ##--- Breadcrum_rails
  add_breadcrumb I18n.t("breadcrumbs." + controller_name), :products_path, only: [:index, :new, :show, :edit]
  add_breadcrumb "Nuevo " + I18n.t("breadcrumbs." + controller_name).singularize, :new_product_path, only: :new
  add_breadcrumb "Detalle del " + I18n.t("breadcrumbs." + controller_name).singularize, :product_path, only: :show
  add_breadcrumb "Editar " + I18n.t("breadcrumbs." + controller_name).singularize, :edit_product_path, only: :edit

  add_breadcrumb "Seguimiento de productos", :product_track_path, only: :product_track

  before_action :set_product, only: [:show, :edit, :update, :destroy]
  before_action :set_product_id, only: [:list_prices, :list_prices_variants, :edit_variants, :update_variants, :edit_from_purchase, :update_from_purchase, :update_status]
  before_action :get_categories, only: [:create, :update]
  before_action :get_attrs, only: [:show, :edit, :update]
  before_action :get_filters, only: [:index, :show, :edit, :new]

  skip_before_action :get_categories, only:  [:edit_from_purchase]
  # GET /products
  # GET /products.json
  def index
    respond_to do |format|
      format.html
      format.json { render json: ProductsDatatable.new(view_context, current_user) }
    end
  end

  def list_prices
    if @product.presentation
      # @available_products = @product.get_available_children(false)
      @pointsales = @product.get_available_children(true)
    end
  end

  def list_prices_variants
    children = Product.where("parent_id = ? and status != 0 ", params[:product_id]).pluck(:id)
    @variants = AvailableProduct.where("pointsale_id = ? and product_id IN (?)", params[:pointsale_id], children).includes(:product)
    @variants_json = Array.new
    @variants.each do |v|
      @variants_json.push(name: v.product.sku + " " + v.product.name + " <br><small>" + v.product.display_attributes + "</small>", price: v.product.get_price_sale(params[:pointsale_id]), available_product_id: v.id)
    end
    render json: @variants_json.to_json
  end

  def edit_variants; end

  def update_variants
    if @product.is_parent
      @product.update_attributes_to_variants(params[:new_size_list], params[:new_color_list], params[:new_style_list])
      @product.save_new_attributes(params[:mynewsizes], params[:mynewcolors], params[:mynewstyles])
    end
    respond_to do |format|
      if @product.save(validate:  false)
        format.html { redirect_to products_url, success: 'Se modificaron las variantes del producto ' + @product.sku + ' - ' + @product.name + '.' }
        format.json { render :show, status: :ok, location: @product }
      else
        format.html { render :edit_variants }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

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

  # GET /products/new
  def new
    @product = Product.new
    # Default unit is 'Pieza'
    @product.unit = Unit.where(unit: 'Pieza').first
    if params[:remoto].present?
      @remoto = params[:remoto]
      @pointsale = params[:pointsale]
      @warehouse = params[:warehouse]
      @supplier = params[:supplier]
      @exchange = params[:exchange]
    end
    @product.price_base = nil
    @product.price_sale = nil
  end

  # GET /products/1/edit
  def edit
    has_variants = @product.children.any?
    @with_presentation = has_variants ? true : false # si aun no tiene variantes, permitir clickear el switch
  end

  # POST /products
  # POST /products.json
  # rubocop:disable Metrics/BlockLength
  def create
    @with_presentation = true
    @product = Product.new(product_params)
    if @product.presentation
      @product.is_parent = true
    end
    message = 'El producto ' + @product.sku + ' fue creado.'
    @product.audit_comment = message
    respond_to do |format|
      if @product.save
        @product.save_variants(current_user)
        ##--- Para cuando se agrega un producto desde purchase
        if params[:remoto] == "true"
          ##--- Guardar pre_purchase
          @pre_purchases = Array.new
          if @product.presentation && @product.is_parent
            @product.children.each do |variant|
              save_pre_purchase(variant)
              set_available
              @pre_purchases << @pre_purchase
            end
          else
            save_pre_purchase(@product)
            set_available
            @pre_purchases << @pre_purchase
          end
          format.json { head :no_content }
          format.js
        else
          # crear available product para el p.v, cuando es sin variantes
          if current_user.usertype == 'G' && !@product.presentation && !@product.is_parent
            AvailableProduct.create(product_id: @product.id, pointsale_id: current_user.pointsale_id, stock: 0)
          end
          format.html { redirect_to products_url, success: message }
          format.json { render :show, status: :created, location: @product }
        end
      else
        format.html { render :new }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end
  # rubocop:enable Metrics/BlockLength

  # PATCH/PUT /products/1
  # PATCH/PUT /products/1.json
  def update
    respond_to do |format|
      @product.skip_sku_validation = true
      @product.is_parent = params[:product][:presentation] == 'true' ? true : false
      message = 'El producto ' + @product.sku + ' fue modificado.'
      @product.audit_comment = message
      if @product.update(product_params)
        if @product.is_parent
          @product.children.each_with_index do |variant, index|
            variant.skip_sku_validation = true
            params_to_edit = product_params
            params_to_edit[:sku] = @product.sku + (index + 1).to_s + "A"
            variant.update_attributes(params_to_edit)
          end
        end
        format.html { redirect_to products_url, success: message }
        format.json { render :show, status: :ok, location: @product }
      else
        format.html { render :edit }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  def edit_from_purchase
    respond_to do |format|
      purchase_in_dollars = params[:is_in_dollars]
      exchange = params[:exchange].to_f
      if purchase_in_dollars == "true"
        @product.price_base_dollars = params[:product][:price_base].to_f
        price_in_peso = @product.price_base_dollars * exchange
        @product.price_base = @product.price_base.present? ? price_in_peso : nil
        @suggested_price_sale = (price_in_peso * (@pos_config.gain_margin / 100)) + price_in_peso
      else
        @product.price_base = params[:product][:price_base].to_f
        price_in_dollars = @product.price_base / exchange if exchange != 0
        @product.price_base_dollars = @product.price_base_dollars.present? ? price_in_dollars : nil
        @suggested_price_sale = (@product.price_base * (@pos_config.gain_margin / 100)) + @product.price_base
      end
      @product.audit_comment = 'El producto ' + @product.sku + ' fue modificado.'
      @product.save
      format.json { head :no_content }
      format.js
    end
  end

  def update_from_purchase
    ##--- Si el producto es hijo, sacar el registro del padre para cambiar todos los valores
    unless @product.parent_id.nil?
      @product = Product.find(@product.parent_id)
    end

    message = "Se ha modificado el precio de venta base del producto " + @product.name
    respond_to do |format|
      if @product.update(product_params)
        @product.children.each do |variant|
          variant.update_attributes(product_params)
          variant.save
        end
        @product.audit_comment = message
        format.json { head :no_content }
        format.js { flash[:success] = message }
      else
        format.js { render :edit_from_purchase }
        format.json { render json: @available_product.errors, status: :unprocessable_entity }
      end
    end
  end

  def update_status
    product = @product

    if product.active?
      product.status = 2
    elsif product.inactive?
      product.status = 1
    end

    if product.presentation
      product.children.each do |pv|
        pv.status = product.status
        pv.save(validate: false)
      end
    end
    respond_to do |format|
      message = "El producto " + product.name + " fue " + (product.active? ? "activado" : "desactivado") + "."
      product.audit_comment = message

      if product.save(validate: false)
        format.html { redirect_to products_url, warning: message }
        # format.json { render :show, status: :ok, location: @pointsale }
        format.json { head :no_content }
      else
        format.html { redirect_to products_url }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /products/1
  # DELETE /products/1.json
  def destroy
    respond_to do |format|
      message = "El producto " + @product.name + " fue eliminado."
      @product.audit_comment = message
      if @product.update_attributes(status: 0)
        if @product.is_parent
          @product.children.each_with_index do |variant|
            variant.update_attributes(status:  0)
            variant.save
          end
        end
        format.html { redirect_to products_url, warning: message }
        format.json { head :no_content }
      else
        format.html { redirect_to products_url }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  def validate_unique_barcode
    respond_to do |format|
      @product = Product.find_by(barcode: params[:barcode])
      if @product.blank?
        format.js { head :ok }
      else
        format.js
      end
    end
  end

  def product_track
    #--Seguimiento de productos
    # @sales = SalesDetail.new
    product_id = params[:product_id]
    pointsale_id = params[:pointsale_id]
    start_date = DateTime.parse(params[:start_date]) if params[:start_date].present?
    end_date = DateTime.parse(params[:end_date]) if params[:end_date].present?
    if product_id.present?
      respond_to do |format|
        @sales = pointsale_id.present? ? Pointsale.find(pointsale_id).sales_details.includes(:sale).where(sales: { date_sale: start_date..end_date }).where('sales.status != 1 and sales_details.product_id = ?', product_id).order("sales_details.id DESC") : SalesDetail.includes(:sale).where(sales: { date_sale: start_date..end_date }).where('sales.status != 1 and sales_details.product_id = ?', product_id).order("sales_details.id DESC")
        format.js
      end
    end
  end

  private

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

  def set_product_id
    @product = Product.find(params[:product_id])
  end

  def get_filters
    @current_page = params[:current_page].blank? ? 1 : params[:current_page]
    @filter = params[:filter]
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def product_params
    params.require(:product).permit(:sku, :name, :description, :price_base, :price_sale, :img_product, :img_product_cache, :presentation, :inventory, :unit_id, :content, :status, :categorias, :category_ids, :include_purchase_tax, :include_sale_tax, :barcode, :is_in_dollars, :price_base_dollars, size_list: [], color_list: [], style_list: [], available_products_attributes: [:id, :price_sale])
  end

  def get_categories
    @categories = Array.new
    unless params[:product][:category_ids].blank?
      @categories << Category.find(params[:product][:category_ids])
      @product.categories = @categories
    end
  end

  def save_pre_purchase(product)
    @pre_purchase = PrePurchase.new
    @pre_purchase.supplier_id = params[:supplier]
    @pre_purchase.pointsale_id = params[:pointsale] if params[:pointsale].present?
    @pre_purchase.warehouse_id = params[:warehouse] if params[:warehouse].present?
    @pre_purchase.exchange = params[:exchange] if params[:exchange].present?

    @pre_purchase.user_id = current_user.id
    @pre_purchase.product_id = product.id
    @pre_purchase.quantity = 1
    @pre_purchase.get_totals
    @pre_purchase.save
  end

  def set_available
    ##--- agregar a productos disponibles ya sea punto de venta o almacen
    if params[:pointsale].present?
      available_product = AvailableProduct.new
      available_product.pointsale_id = @pre_purchase.pointsale_id
    else
      available_product = WarehouseStock.new
      available_product.warehouse_id = @pre_purchase.warehouse_id
    end
    available_product.product_id = @pre_purchase.product_id
    available_product.stock_min = params[:stock_min]
    available_product.stock_max = params[:stock_max]
    available_product.save
  end

  def get_attrs
    @attrs = Array.new
    @product.variants_attributes.each do |attri|
      @attrs << attri.context
    end
  end
end
