module Comee
  module Core
    class SalesOrder < ApplicationRecord
      OWN = "Own".freeze
      AGENT = "Agent".freeze
      SHIPPING_ARRANGEMENTS = [OWN, AGENT].freeze

      before_validation :generate_order_number, if: proc { |so| so.order_number.nil? }

      before_save :set_parent_client_name

      belongs_to :customer_order
      belongs_to :fulfillment_center, optional: true
      belongs_to :client
      belongs_to :shipment_address,
                 -> { where(address_type: ClientAddress::SHIPPING_ADDRESS) },
                 class_name: "Comee::Core::ClientAddress",
                 optional: true
      belongs_to :delivery_address,
                 -> { where(address_type: ClientAddress::DELIVERY_ADDRESS) },
                 class_name: "Comee::Core::ClientAddress"
      belongs_to :invoice_address,
                 -> { where(address_type: ClientAddress::INVOICING_ADDRESS) },
                 class_name: "Comee::Core::ClientAddress"
      has_many :sales_order_items
      has_many :additional_services
      has_many_attached :files
      has_one :customs_detail

      enum :status, {draft: 0, submitted: 1, confirmed: 2, accepted: 3, canceled: 4}
      enum :purchase_status, {unprocessed: 0, processed: 1}

      validates :order_number, presence: true, uniqueness: true
      validates :order_date, :status, :purchase_status, presence: true
      validates :payment_penalty, numericality: {greater_than_or_equal_to: 0, less_than_or_equal_to: 100}, allow_nil: true
      validates :shipping_arrangement, inclusion: {in: SHIPPING_ARRANGEMENTS}, allow_nil: true
      validates :amount_paid,
                presence: true,
                numericality: {greater_than_or_equal_to: 0},
                allow_nil: true

      def calculate_total_price
        self.total_price = calculate_total
      end

      def calculate_vat
        return unless client.tax_code == "Inland"

        self.vat = (calculate_total * 0.19).round(2)
      end

      def calculate_total
        order_items = SalesOrderItem.where(sales_order_id: id)
        services = AdditionalService.where(sales_order_id: id)
        (order_items.sum(&:total_price) + services.sum(&:total_price)).round(2)
      end

      def set_parent_client_name
        self.parent_client_name = client.parent&.name
      end

      def self.ransackable_attributes(_auth_object = nil)
        %w[
          id
          order_number
          status
          purchase_status
          consignee
          destination
          customer_order_id
        ]
      end

      def self.ransackable_associations(_auth_object = nil)
        %w[client customer_order]
      end

      def files_url
        files.attached? ? files.map { |file| Rails.application.routes.url_helpers.rails_blob_url(file, only_path: false) } : []
      end

      def generate_order_number
        self.order_number = Util.generate_number("SalesOrder", "order_number")
      end
    end
  end
end