Spree::Api::OrdersController.class_eval do

  skip_before_action :authenticate_user, only: :ogcreateorder
  skip_before_action :find_order, only: :ogcreateorder

  def ogcreateorder

    #****************************
    # linux shell call to this api
    # curl -X POST -H "Content-Type: text/xml" -d "@og_test1.xml" --header "X-Spree-Token: your_customers_user_key" local.naturalwellbeing.com:8080/api/orders/ogcreateorder
    # assume og_test1.xml should be in you current folder here.  X-Spree-Token is from spree_users

    #****************************

    og_logger ||= Logger.new("#{Rails.root}/log/og.log")
    # 0. get the RC4 Hash key
    merchant_id= Spree::OrdergrooveConfiguration.account["#{current_store.code}"]["og_merchant_id"]
    hashkey= Spree::OrdergrooveConfiguration.account["#{current_store.code}"]["og_hashkey"]
    rc4=RC4.new(hashkey)
    #begin
    # 1. parse xml (rails active support)
    #render :text => 'xml for orderOgId is: ' + params['order']['head']['orderOgId']

    # 2. check all parameters there
    # rails4 seems not recognizing xml as params
    string = request.body.read
    params = Hash.from_xml(string)

    errstr='parameter in OG xml is not complete'

    og_logger.info("#{Time.zone.at(Time.new()).strftime("%B %d, %Y at %I:%M PST")} :\n Start processing og dropped order: #{params.to_xml}")  # this xml is the re-generated one
    og_logger.info "#params.inspect"

    # 2.5 validate xml data ingrety
    strxml_error=''
    if params['order']['customer']['customerFirstName'].blank?
      strxml_error += 'customer first name blank,'
    end
    if params['order']['customer']['customerLastName'].blank?
      strxml_error += 'customer last name blank,'
    end
    if params['order']['customer']['customerShippingAddress1'].blank?
      strxml_error += 'customer shipping address blank,'
    end
    if params['order']['customer']['customerShippingCity'].blank?
      strxml_error += 'customer shipping city blank,'
    end
    if params['order']['customer']['customerShippingState'].blank?
      strxml_error += 'customer shipping state blank,'
    end
    if params['order']['customer']['customerShippingCountry'].blank?
      strxml_error += 'customer shipping country blank,'
    end
    if params['order']['customer']['customerShippingZip'].blank?
      strxml_error += 'customer shipping zip code blank,'
    end
    if params['order']['customer']['customerShippingPhone'].blank?
      strxml_error += 'customer shipping phone blank,'
    end

    if params['order']['customer']['customerBillingAddress1'].blank?
      strxml_error += 'customer Billing address blank,'
    end
    if params['order']['customer']['customerBillingCity'].blank?
      strxml_error += 'customer Billing city blank,'
    end
    if params['order']['customer']['customerBillingState'].blank?
      strxml_error += 'customer Billing state blank,'
    end
    if params['order']['customer']['customerBillingCountry'].blank?
      strxml_error += 'customer Billing country blank,'
    end
    if params['order']['customer']['customerBillingZip'].blank?
      strxml_error += 'customer Billing zip code blank,'
    end
    if params['order']['customer']['customerBillingPhone'].blank?
      strxml_error += 'customer Billing phone blank,'
    end
    if params['order']['customer']['customerPartnerId'].blank? && params['order']['customer']['customerEmail'].blank?
      strxml_error += 'customer customerEmail or customerPartnerId can not be both blank,'
    end
    if strxml_error.length>0
      render :xml =>'<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>130</errorCode><errorMsg>' + strxml_error + '</errorMsg></order>'
    else



      # 3. create order
      if params['order']['customer']['customerPartnerId'].blank?
        user=Spree::User.find_by_email(params['order']['customer']['customerEmail'])
      else
        user=Spree::User.find(params['order']['customer']['customerPartnerId'])
      end
      if !user
        render :xml =>'<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>130</errorCode><errorMsg>User does not exist</errorMsg></order>'
      else

        order=user.orders.create(:store_id=>current_store.id, :item_total=>params['order']['head']['orderSubtotalValue'])

        #order.update_attribute(:user_id, user)  unless !user

        ship_address=Spree::Address.create(:firstname=>params['order']['customer']['customerFirstName'],
                                    :lastname=>params['order']['customer']['customerLastName'],
                                    :address1=>params['order']['customer']['customerShippingAddress1'],
                                    :address2=>params['order']['customer']['customerShippingAddress2'],
                                    :city=>params['order']['customer']['customerShippingCity'],
                                    :state_id=>Spree::State.find_by_abbr(params['order']['customer']['customerShippingState']).id.to_s|| '',
                                    :country_id=>Spree::Country.find_by_iso(params['order']['customer']['customerShippingCountry']).id.to_s||'',
                                    :zipcode=>params['order']['customer']['customerShippingZip'],
                                    :phone=>params['order']['customer']['customerShippingPhone']
        )
        ship_address.save!

        bill_address=Spree::Address.create(:firstname=>params['order']['customer']['customerFirstName'],
                                    :lastname=>params['order']['customer']['customerLastName'],
                                    :address1=>params['order']['customer']['customerBillingAddress1'],
                                    :address2=>params['order']['customer']['customerBillingAddress2'],
                                    :city=>params['order']['customer']['customerBillingCity'],
                                    :state_id=>Spree::State.find_by_abbr(params['order']['customer']['customerBillingState']).id.to_s|| '',
                                    :country_id=>Spree::Country.find_by_iso(params['order']['customer']['customerBillingCountry']).id.to_s||'',
                                    :zipcode=>params['order']['customer']['customerBillingZip'],
                                    :phone=>params['order']['customer']['customerBillingPhone']
        )
        bill_address.save!
        if params['order']['customer']['customerShippingCountry']=="CA"
          shipping_method=Spree::ShippingMethod.find_by_code('USP1')
        else
          if ['HI','AK'].include? params['order']['customer']['customerShippingState']   #hi, ak use usps
            shipping_method=Spree::ShippingMethod.find_by_code('M03')||Spree::ShippingMethod.find_by_zone_id_and_code(2,'U11R')
          else
            shipping_method=Spree::ShippingMethod.find_by_code('SUR')||Spree::Zone.find(2).shipping_methods.select{|s|s.code=='FSP'}
          end
        end
        order.update_attributes(:email=>params['order']['customer']['customerEmail'], :ship_address_id=>ship_address.id, :bill_address_id=>bill_address.id, :shipping_method_id => shipping_method.id)



        order.shipments.each do |shipment|
          shipment.update_attributes(:address_id=>ship_address.id,:cost=>params['order']['head']['orderShipping'].to_f)
        end


        og_discount=[]
        if params['order']['items']['item'].class == Array
          items=params['order']['items']['item']
          else
          items=[params['order']['items']['item']]
        end



          items.each do |item|

            #byebug
            variant=Spree::Variant.find(item['product_id'].to_i)
            line_item=order.contents.add(
                variant,
                item['qty'].to_i || 1,
                {auto_delivery: true, price: item['price']}
            )
            Spree::Adjustment.create(:order_id=>order.id, :amount=>item['discount'].to_f*(-1),:label =>'Auto Delivery Discount', :source_type => "Spree::PromotionAction", :adjustable_id => line_item.id, :adjustable_type => "Spree::LineItem") # discount


          end
         order.create_proposed_shipments

        order.line_items.each do |line_item|
            variant=Spree::Variant.find(line_item['variant_id'])
            if (variant.respond_to? :assembly) && variant.assembly?
              variant.parts.each do|v|
                line_item['quantity'].to_i.times {
                  v.count.to_i.times {
                    order.inventory_units.create(:variant_id=>v.id,:state=>'sold', :shipment_id=>order.shipments.first.id, :line_item_id=>line_item.id)
                  }
                }
              end
            else
              line_item['quantity'].to_i.times {
                order.inventory_units.create(:variant_id=>variant.id,:state=>'sold', :shipment_id=>order.shipments.first.id, :line_item_id=>line_item.id)
              }
            end
          end



        order.reload
        #order.update_totals
        order.total = params['order']['head']['orderTotalValue'].to_f
        #order.item_total = params['order']['head']['orderSubtotalValue'].to_f

        order.line_items.each do |l|
          l.auto_delivery= true
        end

        #order.save!
        #order.adjustments.first.destroy

        #order.adjustments.select{|a| a.source_type=="Spree::TaxRate"}.first.amount=params['order']['head']['orderSalesTax'].to_f
        #order.adjustments.select{|a| a.source_type=="Spree::TaxRate"}.first.save!
        Spree::Adjustment.create(:order_id=>order.id, :amount=>params['order']['head']['orderSalesTax'].to_f, :label =>'Tax', :source_type => "Spree::TaxRate", :adjustable_id => order.id, :adjustable_type => "Spree::Order")


        #shippings=order.adjustments.select{|a| a.source_type=="Spree::ShippingCharge"}

        if params['order']['head']['orderShipping'].to_f == 0.00
          # order.adjustments.select{|a| a.type=="ShippingCharge"}.first.destroy
        end
        #order.line_items.each do |line_item|
        #Spree::Adjustment.create(:order_id=>order.id, :amount=>4.5*(-1),:label =>'Auto Delivery Discount', :source_type => "Spree::PromotionAction", :adjustable_id => line_item.id, :adjustable_type => "Spree::LineItem") # discount
        #end

        order.save!
        # to overwrite the possilbe tax update to 0, reset the total
        order.total = params['order']['head']['orderTotalValue'].to_f

        # 4. payment
        if params['order']['head']['orderPaymentMethod']== 'CC'
          payment_method=Spree::PaymentMethod.where(:name=>'Credit Card').first

          payment=Spree::Payment.create(:order_id=>order.id,
                                 :amount=>order.total,
                                 :payment_method_id=>payment_method.id
          )

          expire_date=rc4.decrypt(Base64.decode64(params['order']['head']['orderCcExpire'])).split('/')
          payment.source = payment_method.payment_source_class.new(:number=>rc4.decrypt(Base64.decode64(params['order']['head']['orderCcNumber'])),
                                                                   :month=>expire_date[0].to_i.to_s,
                                                                   :year=>expire_date[1],
                                                                   :verification_value=>213, #params['order']['head']['orderCcNumber'],
                                                                   :name=>params['order']['customer']['customerBillingFirstName'] +' '+params['order']['customer']['customerBillingLastName']
          )

          begin
            payment.source.number=rc4.decrypt(Base64.decode64(params['order']['head']['orderCcNumber']))
            payment_method.create_profile(payment)
            order.total=order.item_total+ order.adjustments.map(&:amount).inject(:+)

            payment.started_processing!
            payment.pend!

            order.update_attributes({:state => "complete", :completed_at => Time.now})
            #order.update_attribute(:automated_approved_at, Time.now)
            until order.state == "complete"
              if order.next!
                order.update!
                state_callback(:after)
              end
            end
            order.finalize!
            og_logger.info("og order is successfully created in nwb with number: #{order.number}")
            result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>SUCCESS</code><orderId>' + order.number + '</orderId><errorMsg /></order>'
          rescue Spree::Core::GatewayError => ge
            # if it fails, destroy the payment and clear the autodelivery discount and flag
            payment.destroy
            order.destroy
            ge=ge.to_s
            error_code='140' #ge.params.messages.message.result_code
            if ge.include? ',,,,,,,,'    #this is raw of direct_response

              response_error_code=ge.split(',')[2]
              if %w(17).include? response_error_code
                error_code='100'
              elsif %w(6,28,37,78).include? response_error_code
                error_code='110'
              elsif %w(7,8).include? response_error_code
                error_code='120'
              elsif %w(27,127).include? response_error_code
                error_code='130'
              end
              error_message = ge.params['message'] || ge.params['response_reason_text'] || ge.message
            else
              error_message=ge #'' #ge.params.messages.message.text
            end

            og_logger.info("error happened in making the payment with creditcard: #{ge}")
            result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>' + error_code + '</errorCode><errorMsg>' + error_message + '</errorMsg></order>'
          end
        else
          errstr="The payment method should be CC"
          og_logger.info("error happened in processing og order: #{errstr}")
          result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>999</errorCode><errorMsg>' + errstr + '</errorMsg></order>'

          #raise(errstr)
        end

        # 5. response xml with code and message
        render :xml => result_xml #order.to_xml
      end
    end

  end

end