class Order < ApplicationRecord
  self.primary_key = "order_id"

  #primary key - need to be unique
  before_create :generate_custom_id
  before_create :set_order_date
  has_many :sale_orders
  belongs_to :customer
  has_many :order_items, autosave: true , inverse_of: :order
  has_many :assigned_order_items

  #internal references attributes for business logic control
  attr_accessor :items, :guest, :table_id, :new_booking, :booking_type, :employee_name, :booking_id
  scope :active, -> { where("date BETWEEN '#{DateTime.now.utc.end_of_day}' AND '#{DateTime.now.utc.beginning_of_day}'") }
  #Main Controller method to create new order - validate all inputs and generate new order
  # order_item : {
  #     order_item_code : "",
  #     item_instance_code : "",
  #     quantity : 0,
  #     option_values : [],
  #     sub_order_items : [],
  # }

  def generate
    booking = nil

    if self.new_booking
      booking = Booking.create({:dining_facility_id => self.table_id,:type => "TableBooking",
                                :checkin_at => Time.now.utc, :checkin_by =>  self.employee_name,
                                :booking_status => "assign" })
      table =  DiningFacility.find(self.table_id)
      table.status = "occupied"
      table.save
    else
      booking = Booking.find(self.booking_id)
    end

    booking.save!
    self.default_values

    #  cashier already opened?
    if self.save!

      self.adding_line_items
      #Add Order Table and Room relation afrer order creation
      BookingOrder.create({:booking_id => booking.booking_id, :order => self})

      #Send order to queue one it done!
      process_order_queue

      #send order to broadcast job
      #send_order_broadcast

      return true, booking

    end

    return false

  end

  #Main Method - to update order / add items
  def modify

  end

  def adding_line_items

    if self.items
      #re-order to
      ordered_list = re_order_items(self.items)

      #loop to add all items to order
      self.items.each do |item|
        menu_item = MenuItem.search_by_item_code(item[:item_instance_code])

        #if (!menu_item.nil?)
          Rails.logger.debug menu_item
          set_order_items = nil
          ##If menu Item set item - must add child items to order as well, where price is only take from menu_item
          if (menu_item[:type] == "SetMenuItem")
            set_order_items
          end

          # not insert with price 0
          # puts item[:price]
          # puts item
          # if(item[:price] != 0 )
          #   OrderItem.processs_item(menu_item[:item_code], menu_item[:name], menu_item[:account_id],
          #                 item[:quantity],menu_item[:price], item[:options], set_order_items, self.id,
          #                 self.employee_name)
          # end

          OrderItem.processs_item(menu_item[:item_code], menu_item[:name], menu_item[:alt_name], menu_item[:account_id],
                          item[:quantity],menu_item[:price], item[:options], set_order_items, self.id,
                          self.employee_name)

        #end
      end

      self.item_count = self.order_items.count
      self.save!

      return true
    else
      self.errors.add(:order_items, :blank, message: "Order items cannot be blank")
      return false
    end

  end

  def update_items_status_to_billed(items)
    if (items.nil?)
      ##Update the order status to ensure that reflect the stage
      self.order_items.each do |item|
        item.order_item_status = "billed"
        item.save
      end
    else
      items.each do |item|
        item.order_item_status = "billed"
        item.save
      end
    end
  end

  def default_values
      self.customer = Customer.find(1) if self.customer_id.nil?
      self.source = "emenu" if self.source.nil?
      self.order_type = "dine-in" if self.order_type.nil?

  end

  protected
  def re_order_items(form_items) #reorder inputs items as parents and child
    parent_id = Array.new
    parents = Array.new
    parents_and_children_items = Array.new

    new_items_list = Array.new

    form_items.each do |parent|
      if !parent[:parent_order_item_id].nil?
        if (!parent_id.include?(parent[:parent_order_item_id]))
          parent_id.push(parent[:parent_order_item_id])

        end
      end
    end
    Rails.logger.debug "Parent Id count -> " + parent_id.count.to_s


    parent_id.each do |pid|
      form_items.each do |item|
        Rails.logger.debug "Adding - Parents -> " + pid.to_s + " - " + item[:order_item_id].to_s
          if (pid == item[:order_item_id])
            parents.push(item)
          end
      end
    end
    Rails.logger.debug "Parents count -> " + parents.count.to_s

    parents.each do |parent|
      children = Array.new
      form_items.each do |item|
        if (parent[:order_item_id] == item[:parent_order_item_id] )
          children.push(item)
          #Items to remove for new list
          parents_and_children_items.push(item)
        end
      end
      parent[:sub_items] = children
    end
    Rails.logger.debug "Parent/children Items to remove -> " + parents_and_children_items.count.to_s

    #Remove process items
    #c = a.reject{ |e| b.include? e }

    new_items_list = form_items - parents_and_children_items


    Rails.logger.debug "New list count -> " + new_items_list.count.to_s

    #Add parent to the list
    #new_items_list = new_items_list + parents

    Rails.logger.debug "Re-Order List (Parent)-"

    Rails.logger.debug parents

    Rails.logger.debug "Re-Order List -"
    Rails.logger.debug new_items_list

    return new_items_list
  end


  #Update Items Count and Quantity changes whenever there is changes
  def update_products_and_quantity_count
    item_count = 0
    quantity_count = 0
    # Count number of different items
    self.item_count = self.order_items.item_count
    self.quantity_count = quantity_count
    # Counter number of quantityf
  end

  #Process order items and send to order queue
  def process_order_queue
    #Send to background job for processing
    OrderQueueProcessorJob.perform_later(self.id, self.table_id)
  end


  #send order items and send to order queue
  def send_order_broadcast
    #Send to background job for processing
    OrderBroadcastJob.perform_later(self.id)
  end

  #Origami: Cashier : to view order Table
  def self.get_order_table
    order_table = Order.select("orders.order_id as order_id,sum(order_items.qty*order_items.price) as total_price,
        order_items.order_items_id as order_items_id,dining_facilities.name as table_name")
        .joins("left join booking_orders on booking_orders.order_id = orders.order_id
        left join bookings on bookings.booking_id = booking_orders.booking_order_id
        left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
        left join order_items on order_items.order_id = orders.order_id")
        .where("dining_facilities.type=? and orders.order_type=? and dining_facilities.is_active=?",DiningFacility::TABLE_TYPE,"dine_in",true)
        .group("orders.order_id, order_items.order_items_id,dining_facilities.name")
  end

  #Origami: Cashier : to view booking order Table
  def self.get_booking_order_table
    booking_orders = Booking.select("sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
                        orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
                        bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name")
                    .joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
                    .joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
                    .joins("left join orders on orders.order_id = booking_orders.order_id")
                    .joins("left join sales on sales.sale_id = bookings.sale_id")
                    .where("(orders.status = 'new' or orders.status = 'billed') and (dining_facilities.type=? and dining_facilities.is_active=?)",DiningFacility::TABLE_TYPE,true)
                    .group("bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id")
                    # For PG
                    # booking_orders.order_id IS NOT NULL and dining_facilities.type=? and dining_facilities.is_active=?",DiningFacility::TABLE_TYPE,true
                    # sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id
  end

  #Origami: Cashier : to view booking order Table
  def self.get_completed_order
    completed_orders = Booking.select("sales.receipt_no, sales.sale_status, orders.status as order_status,orders.order_id,
                        bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id")
                    .joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
                    .joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
                    .joins("left join orders on orders.order_id = booking_orders.order_id")
                    .joins("left join sales on sales.sale_id = bookings.sale_id")
                    .where("sales.sale_status='completed'")
                    .group("sales.sale_id,bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id")
                    # For PG
                    #bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id
  end

   #Origami: Cashier : to view order type Room
  def self.get_booking_order_rooms
    booking_rooms = Booking.select("sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
                        orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
                        bookings.booking_id,orders.customer_id as customer_id,
                        sales.sale_id as sale_id,dining_facilities.name as room_name")
                    .joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
                    .joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
                    .joins("left join orders on orders.order_id = booking_orders.order_id")
                    .joins("left join sales on sales.sale_id = bookings.sale_id")
                    .where("(orders.status = 'new' or orders.status = 'billed') and (dining_facilities.type=? and dining_facilities.is_active=?)",DiningFacility::ROOM_TYPE,true)
                    .group("bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.customer_id,orders.order_id")
                    # For PG
                    # booking_orders.order_id IS NOT NULL and dining_facilities.type=? and dining_facilities.is_active=?",DiningFacility::ROOM_TYPE,true
                    # sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.customer_id,orders.order_id
  end

   #Origami: Cashier : to view order type Room
  def self.get_order_rooms
    order_rooms = Order.select("orders.order_id as order_id,sum(order_items.qty*order_items.price) as total_price,
                    order_items.id as order_items_id,dining_facilities.name as room_name")
          .joins("left join booking_orders on booking_orders.order_id = orders.order_id
          left join bookings on bookings.booking_id = booking_orders.order_id
          left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
          left join order_items on order_items.order_id = orders.order_id")
          .where("dining_facilities.type=? and orders.order_type=? and dining_facilities.is_active=?",DiningFacility::ROOM_TYPE,"dine_in",true)
          .group("orders.order_id")
  end

  #Origami: Cashier : to view orders
  def self.get_orders
    from = Time.now.beginning_of_day.utc
    to = Time.now.end_of_day.utc
    orders=Booking.select("sales.receipt_no, sales.sale_status as sale_status, orders.status as order_status,
                        orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
                        bookings.booking_id,orders.customer_id as customer_id,
                        sales.sale_id as sale_id,dining_facilities.name as table_name")
                    .joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
                    .joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
                    .joins("left join orders on orders.order_id = booking_orders.order_id")
                    .joins("left join sales on sales.sale_id = bookings.sale_id")
                    .where("(orders.status = 'new' or orders.status = 'billed') AND orders.date between #{ from } and #{ to }")

    # orders = Order.select("orders.order_id as order_id,sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
    #            orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id
    #           ,bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name")
    #       .joins("left join booking_orders on booking_orders.order_id = orders.order_id
    #       left join bookings on bookings.booking_id = booking_orders.order_id
    #       left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
    #       left join order_items on order_items.order_id = orders.order_id
    #       left join sale_orders on sale_orders.order_id = orders.order_id
    #       left join sales on sales.sale_id = sale_orders.sale_id")
    #       .where("(orders.status = 'new' or orders.status = 'billed')")
    #       .group("orders.order_id")
          # For PG
          # .where("dining_facilities.is_active=? and orders.date between ? and ?",true,from,to)
          # .group("orders.order_id,order_items.order_items_id,dining_facilities.name,sales.receipt_no,bookings.booking_id,sales.sale_id,orders.customer_id")

  end

  def self.search(search)
    if search
      # find(:all, :conditions => ['name LIKE ? OR contact_no LIKE ?', "%#{search}%", "%#{search}%"])
      where("order_id LIKE ?", "%#{search}%")
    else
      find(:all)
    end
  end

  private

  def generate_custom_id
    self.order_id = SeedGenerator.generate_id(self.class.name, "ODR")
  end

  def set_order_date
    self.date = Time.now.utc
  end

end
