class OrderReservation < ApplicationRecord
	self.primary_key = "order_reservation_id"

	#primary key - need to be unique generated for multiple shops
  	before_create :generate_custom_id

	has_many :order_reservation_items
	has_one :delivery

	scope :active, -> { where("created_at BETWEEN '#{DateTime.now.utc.beginning_of_day}' AND '#{DateTime.now.utc.end_of_day}'") }
	scope :latest_order, -> { order("order_reservation_id desc, created_at desc") }

	SEND_TO_KITCHEN = "send_to_kitchen"
	READY_TO_DELIVERY = "ready_to_deliver"
	DELIVERED = "delivered"
	COMPLETED = "completed"

	#new customer for doemal
	def self.addCustomer(params)
		if params[:gender] == "female"
		  gender = "Female"
		else
		  gender = "Male"
		end
		customer = Customer.new
		customer.name             = params[:name]
		customer.email            = params[:email]
		customer.contact_no       = params[:contact_no] ? params[:contact_no] : ''
		customer.gender           = gender
		customer.address          = params[:address] ? params[:address] : ''
		customer.date_of_birth    = params[:date_of_birth] ? Time.parse(params[:date_of_birth]).strftime("%Y-%m-%d") : ''
		customer.membership_id    = params[:membership_id]
		customer.customer_type    = "Doemal"
		customer.tax_profiles     = ["2"]
		customer.save

		# unless customer.valid?
		#     render json: {
		#       status: 422,
		#       message: "Validation error", 
		#       errors: customer.errors    
		#     }.to_json
		#     return
		# end

		return customer
	end

	def self.addOrderReservationInfo(order_reserve)
		Rails.logger.debug order_reserve.to_s
		check_order_reservation = OrderReservation.where("transaction_ref = ?",order_reserve[:reference])
		if check_order_reservation.empty?
			order_reservation = OrderReservation.new
			order_reservation.order_reservation_type = order_reserve[:order_type]
			order_reservation.customer_id = order_reserve[:cus_info]
			order_reservation.requested_time = Time.zone.parse(order_reserve[:requested_time]).utc
			order_reservation.callback_url = order_reserve[:callback_url]
			order_reservation.transaction_ref = order_reserve[:reference]
			if order_reserve[:order_info]
				order_reservation.item_count = order_reserve[:order_info][:items].count
				order_reservation.payment_type = order_reserve[:payment_info][:payment_type]
				order_reservation.payment_status = order_reserve[:payment_info][:payment_status]
				order_reservation.payment_ref = order_reserve[:payment_info][:payment_ref]
				order_reservation.taxes = order_reserve[:payment_info][:taxes].to_json
				order_reservation.total_amount = order_reserve[:payment_info][:sub_total]
				order_reservation.total_tax = order_reserve[:payment_info][:total_tax]
				order_reservation.discount_amount = order_reserve[:payment_info][:discount_amount]
				order_reservation.convenience_charge = order_reserve[:payment_info][:convenience_charge]
				order_reservation.grand_total = order_reserve[:payment_info][:grand_total]
				order_reservation.order_remark = order_reserve[:order_info][:order_remark]
			end
			if order_reserve[:reservation_info]
				order_reservation.total_customer = order_reserve[:reservation_info][:total_user]
				# order_reservation.order_remark = order_reserve[:reservation_info][:reservation_note]
			end
			order_reservation.save!
			if order_reserve[:order_info][:items]
				order_reserve[:order_info][:items].each do |oritem|	
					OrderReservationItem.process_order_reservation_item(oritem[:product_code],oritem[:item_instance_code],oritem[:product_name],oritem[:product_alt_name],
						oritem[:account_id],oritem[:qty],oritem[:price],oritem[:unit_price],
						oritem[:options],nil,order_reservation.id)
				end
			end
			if order_reserve[:delivery_info]
				Delivery.addDeliveryInfo(order_reserve[:delivery_info],order_reservation.id)
			end
			return order_reservation.id, true
		else
			return check_order_reservation[0].id, false
		end
	end

    def self.create_doemal_order(order,current_user)
	    is_extra_time = false
	    extra_time = ''

	    items_arr = []
	    count = 1
	    order.order_reservation_items.each { |i| 
	    	i.item_instance_code = i.item_instance_code.downcase.to_s
	       	items = {"order_item_id": count,"item_instance_code": i.item_instance_code,"quantity": i.qty,"options": i.options}
	       	count += 1
	       	items_arr.push(items)
	    }
      	customer_id = order.customer_id
 
		@order = Order.new
		@order.source     = "doemal_order"
		@order.order_type = "delivery"
		@order.customer_id = customer_id
		@order.items = items_arr
		@order.guest = ''
		@order.table_id = nil  # this is dining facilities's id
		@order.new_booking = true
		@order.waiters = current_user.name
		@order.employee_name = current_user.name

		@order.is_extra_time = is_extra_time
		@order.extra_time    = extra_time

		@status, @booking = @order.generate

      	# Order.send_customer_view(@booking)
        if @status && @booking
        
          @status, @sale = Sale.request_bill(@order,current_user,current_user)

          #order status send to doemal
          callback_response = send_status_to_ordering(order.callback_url,order.transaction_ref,SEND_TO_KITCHEN)
          #order reservation status updated
          update_order_reservation(order.id, @sale.sale_id, SEND_TO_KITCHEN)

          result = {:status=> @status, :data => @sale, :message => "send to kitchen" }
   		else
   			result = {:status=> @status, :message => "No current shift open for this employee!" }
        end

        return result
    end

    def self.update_doemal_payment(order,current_user)
    	if(Sale.exists?(order.sale_id))
	      saleObj = Sale.find(order.sale_id)
	      shop_details =  Shop.first 
	      # rounding adjustment
	      if shop_details.is_rounding_adj
	        a = saleObj.grand_total % 25 # Modulus
	        b = saleObj.grand_total / 25 # Division
	        #not calculate rounding if modulus is 0 and division is even
	        #calculate rounding if modulus is zero or not zero and division are not even
	        if (a != 0.0 && b%2 != 0.0) || (a==0.0 && b%2 !=0)
	          new_total    = Sale.get_rounding_adjustment(saleObj.grand_total)
	          rounding_adj = new_total-saleObj.grand_total
	          saleObj.update_attributes(grand_total: new_total,old_grand_total: saleObj.grand_total,rounding_adjustment:rounding_adj)        
	        end
	      end
	      #end rounding adjustment
	      
	      sale_payment = SalePayment.new
	      sale_payment.process_payment(saleObj, current_user.name, saleObj.grand_total, "cash")

	      #order status send to doemal
          callback_response = send_status_to_ordering(order.callback_url,order.transaction_ref,DELIVERED)
          #order reservation status updated
          update_order_reservation(order.id, saleObj.sale_id, DELIVERED)

	      result = {:status=> true, :message => DELIVERED }
          return result
	    end 
    end

    def self.send_status_to_ordering(url,ref_no,status,waiting_time=nil,min_type=nil,reason=nil)
    	base_url = 'https://api.doemal.com'
    	token = '3T-tnlYtFJ-5Z1vY6XQqxQ'
    	order_reservation = Lookup.collection_of("order_reservation")
    	if !order_reservation.empty?
    		order_reservation.each do |order_reserve|
				if order_reserve[0] == 'BaseURL'
					base_url = order_reserve[1]
				elsif order_reserve[0] == 'Token'
					token = order_reserve[1]
				end
			end
    	else
    		Rails.logger.debug "Add order reservation BaseURL "
    		response = {status: false}
    	end
    	Rails.logger.debug "Doemal URL" + base_url
    	post_url = base_url + url

    	if status == 'processed'
    		status = 'send_to_kitchen'
    	elsif status == 'delivered'
    		status = 'ready_to_deliver'
    	elsif status == 'completed'
    		status = 'delivered'
    	else
    		status = status
    	end

    	if waiting_time != ""
    		send_params = {id: ref_no,type: min_type, waiting_time: waiting_time, status: status}
    	elsif reason != ""
    		send_params = {id: ref_no, status: status, reason: reason}
    	else
    		send_params = {id: ref_no, status: status}
    	end

    	begin
	      response = HTTParty.post(post_url,
	              :body => send_params.to_json,
	              :headers => {
	                        'Authorization' => 'Token token='+token,
	                        'Content-Type' => 'application/json',
	                        'Accept' => 'application/json; version=3'
	              }, :timeout => 10
	        )
	    rescue Net::OpenTimeout
	        response = { status: false }

	    rescue OpenURI::HTTPError
	        response = { status: false}
	    rescue SocketError
	        response = { status: false}
	    end
		Rails.logger.debug "Get Doemal Status "
		Rails.logger.debug response.to_json
		return response
    end

    def self.update_order_reservation(id, sale_id, status, expected_waiting_time=nil, remark=nil, access_code=nil, current_user=nil)
    	order_reservation  = OrderReservation.find(id)
    	if sale_id.present?
    		order_reservation.sale_id = sale_id
    	end
    	if !expected_waiting_time.nil?
    		order_reservation.expected_waiting_time = expected_waiting_time
    	end
    	if !status.nil?
    		order_reservation.status = status
    	end
    	if !remark.nil?
    		order_reservation.order_remark = remark
    	end
    	if status == "delivered"
    		order_reservation.payment_status = "paid"
    	end
    	order_reservation.save

    	# if !order_reservation.sale_id.nil? && status == "rejected"
    	# 	void_doemal_payment(order_reservation.sale_id, remark, access_code, current_user)
    	# end
    end

    def self.void_doemal_payment(sale_id, remark, access_code, current_user)
	    if Sale.exists?(sale_id)
	      sale = Sale.find_by_sale_id(sale_id)
	      # update count for shift sale
	      if(sale.sale_status == "completed")
	        if sale.shift_sale_id != nil
	          shift = ShiftSale.find(sale.shift_sale_id)
	          shift.calculate(sale_id, "void")
	        end
	      else
	        # void before sale payment complete
	        if sale.shift_sale_id != nil
	          shift = ShiftSale.find(sale.shift_sale_id)
	          shift.total_void = shift.total_void + sale.grand_total
	          shift.save
	        end
	      end
	            
	      sale.payment_status = 'void'
	      sale.sale_status = 'void'
	      sale.save

	      # FOr Sale Audit 
	      action_by = current_user.name
	      approved_by = Employee.find_by_emp_id(access_code)
	      # remark = "Void Sale ID #{sale_id} | Receipt No #{sale.receipt_no} | Receipt No #{sale.receipt_no} | Table ->#{table.name}"
	      sale_audit = SaleAudit.record_audit_for_edit(sale_id,sale.cashier_id, approved_by.name,remark,"SALEVOID" )

	      # update complete order items in oqs
	      SaleOrder.where("sale_id = '#{ sale_id }'").find_each do |sodr|        
	        AssignedOrderItem.where("order_id = '#{ sodr.order_id }'").find_each do |aoi|
	          aoi.delivery_status = 1
	          aoi.save
	        end
	      end
	    end
    end

    def self.get_count_on_order
    	order_reservation = OrderReservation.select("COUNT(order_reservation_id) as count, status")
    						.where("status != 'delivered'")
    						.group("status")
    end

    def self.get_count_on_completed
    	order_reservation = OrderReservation.select("COUNT(order_reservation_id) as count")
    						.where("created_at BETWEEN '#{DateTime.now.beginning_of_day}' AND '#{DateTime.now.end_of_day}' AND status = 'delivered'").first()
    end

    def self.get_pending_orders
    	order_reservation = OrderReservation.select("order_reservations.*,del.provider,del.delivery_type")
    						.joins(" JOIN deliveries as del on del.order_reservation_id=order_reservations.order_reservation_id")
    						.where("order_reservations.status='new'")
    						.order("order_reservations.order_reservation_id desc, order_reservations.created_at desc")
    end

    def self.check_new_order
    	shop = Shop.find_by_id(1)
    	if !shop.shop_code.nil?
			shop_code = shop.shop_code
		else
			shop_code = ''
		end
    	order_reservation = OrderReservation.where("status='new'")
    	if order_reservation.length > 0
    		if ENV["SERVER_MODE"] == 'cloud'
              from = request.subdomain  + "." + request.domain
              ActionCable.server.broadcast "check_new_order_channel",data: order_reservation, shop_code: shop_code,from:from
            else 
              from = ""
            end
			# if ENV["SERVER_MODE"] == 'cloud'
			# 	ActionCable.server.broadcast "check_new_order_channel",data: order_reservation, shop_code: shop_code
			# end
		end
    end

    def self.check_order_send_to_kitchen
    	shop = Shop.find_by_id(1)
    	if !shop.shop_code.nil?
			shop_code = shop.shop_code
		else
			shop_code = ''
		end
    	order_reservation = OrderReservation.where("status='accepted' and requested_time <= '#{Time.now.utc}'")
    	if order_reservation.length > 0
    		if ENV["SERVER_MODE"] == 'cloud'
              from = request.subdomain  + "." + request.domain
              ActionCable.server.broadcast "check_order_send_to_kitchen_channel",data: order_reservation, shop_code: shop_code,from:from
            else 
              from = ""
            end
			# if ENV["SERVER_MODE"] == 'cloud'
			# 	ActionCable.server.broadcast "check_order_send_to_kitchen_channel",data: order_reservation, shop_code: shop_code
			# end
		end
    end

    def self.check_order_ready_to_delivery
    	shop = Shop.find_by_id(1)
    	if !shop.shop_code.nil?
			shop_code = shop.shop_code
		else
			shop_code = ''
		end
    	order_reservation = OrderReservation.where("status='send_to_kitchen' and requested_time <= '#{Time.now.utc}'")
    	if order_reservation.length > 0
    		if ENV["SERVER_MODE"] == 'cloud'
              from = request.subdomain  + "." + request.domain
              ActionCable.server.broadcast "check_order_ready_to_delivery_channel",data: order_reservation, shop_code: shop_code,from:from
            else 
              from = ""
            end
		end
    end

    def self.get_order_reservation_by_shift(shift_sale_range,shift,from,to,provider)
	    ## => left join -> show all sales although no orders
	    if provider.blank?
	      provider = ''
	    else
	      if provider.present?
	        provider = " and deliveries.provider = '#{provider}'"
	      end
	    end

	    query = OrderReservation.select("order_reservations.*, deliveries.provider, deliveries.delivery_fee, customers.name, customers.email")
	    						.joins(" JOIN deliveries on deliveries.order_reservation_id = order_reservations.order_reservation_id")
	    						.joins(" JOIN customers on customers.customer_id = order_reservations.customer_id")
	    						.joins(" JOIN sales on sales.sale_id = order_reservations.sale_id")
	    if shift.present?
	      query = query.where("sales.shift_sale_id in (?) #{provider} and sales.sale_status= 'completed' and sale_payments.payment_amount != 0", shift.to_a)
	              .joins("join sale_payments on sale_payments.sale_id = sales.sale_id")
	              .group("sales.sale_id")
	    elsif shift_sale_range.present?
	      query = query.where("sales.sale_status='completed' #{provider} and sale_payments.payment_amount != 0 and sales.shift_sale_id in (?)",shift_sale_range.to_a)
	              .joins("join sale_payments on sale_payments.sale_id = sales.sale_id")
	              .group("sales.sale_id")
	    else
	      query = query.where("sales.sale_status='completed' and sales.receipt_date between ? and ? #{provider} and sale_payments.payment_amount != 0",from,to)
	              .joins("join sale_payments on sale_payments.sale_id = sales.sale_id")
	              .group("sales.sale_id")
	    end
	    return query
	end

	def self.search(filter,from,to)
		if filter.blank?
		    keyword = ''
		else
		    keyword = "status LIKE '%#{filter}%'"
		end

		if from.present? && to.present?
		    order_reservation = OrderReservation.select("order_reservations.*, deliveries.provider, deliveries.delivery_fee")
		    					.joins(" JOIN deliveries on deliveries.order_reservation_id = order_reservations.order_reservation_id")
		    					.where("order_reservations.created_at >= ?" + " AND order_reservations.created_at <= ? and NOT status = 'new' ", from,to)
		    query = order_reservation.where(keyword)
		else
		    select("order_reservations.*, deliveries.provider, deliveries.delivery_fee")
		    .joins(" JOIN deliveries on deliveries.order_reservation_id = order_reservations.order_reservation_id")
		    .where("status LIKE '%#{filter}%'")
		end
	end

	private
		def generate_custom_id
			self.order_reservation_id = SeedGenerator.generate_id(self.class.name, "ODRS")
		end
end
