module Comee
  module Core
    class SalesOrderItem < ApplicationRecord
      default_scope { order(serial_no: :asc) }

      before_save :calculate_total_price, :calculate_handover_date, :calculate_price_change, :calculate_quantity_change
      after_save :update_sales_order
      after_save :update_sales_order_purchase_status, if: proc { |item| item.fully_processed? }
      after_destroy :update_sales_order

      enum processing_status: {unprocessed: 0, partially_processed: 1, fully_processed: 2}

      belongs_to :sales_order
      belongs_to :customer_order_item
      belongs_to :product
      belongs_to :unit
      belongs_to :source, class_name: "Comee::Core::FulfillmentCenter", optional: true
      belongs_to :purchase_order_item, optional: true
      has_many :shipment_items

      validates :serial_no, :customer_item_no, :customer_item_description, :delivery_date, :processing_status, presence: true
      validates :quantity, :price, presence: true, numericality: {greater_than: 0}
      validates :quantity_delivered, :quantity_canceled, numericality: {greater_than_or_equal_to: 0}
      validates :serial_no, numericality: {greater_than: 0, only_integer: true}

      delegate(:po_number, to: :purchase_order_item, prefix: false, allow_nil: true)

      def calculate_handover_date
        return if handover_date

        self.handover_date = sales_order.handover_date
      end

      def calculate_total_price
        self.total_price = (price * quantity).round(2)
      end

      def update_sales_order
        sales_order.calculate_total_price
        sales_order.calculate_vat
        sales_order.save!
      end

      def calculate_price_change
        return if customer_order_item.unit_id == unit_id && customer_order_item.price == price

        if customer_order_item.unit_id == unit_id
          self.price_diff = price - customer_order_item.price
        else
          service = CustomerOrderService.new
          co_price = service.convert_price(customer_order_item.price, customer_order_item.unit_id, unit_id)
          self.price_diff = price - co_price
        end
      end

      def calculate_quantity_change
        return if customer_order_item.unit_id == unit_id && customer_order_item.quantity == quantity

        if customer_order_item.unit_id == unit_id
          self.quantity_diff = quantity - customer_order_item.quantity
        else
          service = CustomerOrderService.new
          co_quantity = service.convert_quantity(customer_order_item.quantity, customer_order_item.unit_id, unit_id)
          self.quantity_diff = quantity - co_quantity
        end
      end

      def quantity_remaining
        quantity - (quantity_delivered + quantity_canceled)
      end

      def update_sales_order_purchase_status
        return unless sales_order.sales_order_items.all.all?(&:fully_processed?)

        sales_order.purchase_status = SalesOrder.purchase_statuses[:processed]
        sales_order.save!
      end

      def self.ransackable_attributes(_auth_object = nil)
        %w[
          id
          customer_item_no
          customer_item_description
          customer_order_item_id
          delivery_date
          eb_number
          handover_date
          lead_time
          product_id
          sales_order_id
          purchase_order_item_id
          source_id
          unit_id
          processing_status
        ]
      end

      def self.ransackable_associations(_auth_object = nil)
        %w[customer_order_item product sales_order purchase_order_item source unit]
      end
    end
  end
end