# == Schema Information
#
# Table name: carts
#
#  id                   :integer          not null, primary key
#  created_at           :datetime         not null
#  updated_at           :datetime         not null
#  delivery_id          :integer
#  country              :string
#  delivery_service_ids :text
#

require 'rails_helper'

describe Cart, broken: true do

    store_setting

    # ActiveRecord relations
    it { expect(subject).to have_many(:cart_items).dependent(:destroy) }
    it { expect(subject).to have_many(:cart_item_accessories).through(:cart_items) }
    it { expect(subject).to have_many(:skus).through(:cart_items) }
    it { expect(subject).to have_one(:order) }
    it { expect(subject).to belong_to(:delivery).class_name('DeliveryServicePrice') }


    describe "When retrieving the cart total value" do
        let!(:cart) { create(:cart) }
        let!(:cart_item_1) { create(:cart_item, price: "12", quantity: 1, cart: cart) }
        let!(:cart_item_2) { create(:cart_item, price: "6.50", quantity: 4, cart: cart) }
        let!(:cart_item_3) { create(:cart_item, price: "3.20", quantity: 2, cart: cart) }

        it "should iterate through all cart items and calculate the sum" do
            expect(cart.cart_items.count).to eq 3
            expect(cart.cart_items.sum('quantity')).to eq 7
            expect(cart.total_price).to eq BigDecimal.new("44.40")
        end
    end

    describe "When viewing a cart" do
        let(:cart) { create(:full_cart) }
        let(:calculated_cart) { cart.calculate(20.0)}


        it "should return a hash containing the correct net amount total" do
            expect(calculated_cart[:subtotal]).to eq cart.total_price
        end

        context "if the cart has no associated delivery estimate" do

            it "should return a hash containing the correct delivery total" do
                expect(calculated_cart[:delivery]).to eq 0
            end

            it "should return a hash containing the correct tax amount total" do
                expect(calculated_cart[:tax]).to eq cart.total_price * 20.0
            end

            it "should return a hash containing the correct gross amount total" do
                expect(calculated_cart[:total]).to eq (cart.total_price + (cart.total_price * 20.0))
            end
        end

        context "if the cart has an associated delivery estimate" do
            let!(:delivery) { create(:delivery_service_price) }
            let(:cart) { create(:full_cart, delivery: delivery) }
            let(:calculated_cart) { cart.calculate(20.0) }

            it "should return a hash containing the correct tax amount total, with the delivery esimate price" do
                expect(calculated_cart[:tax]).to eq (cart.total_price + cart.delivery.price) * 20.0
            end

            it "should return a hash containing the correct delivery total" do
                expect(calculated_cart[:delivery]).to eq cart.delivery.price
            end

            it "should return a hash containing the correct gross amount total, wih the delivery estimate price" do
                expect(calculated_cart[:total]).to eq (cart.total_price + cart.delivery.price + ((cart.total_price + cart.delivery.price) * 20.0))
            end
        end
    end

    # weight 22.67
    # length 67.2
    # thickness 12.34
    # Follows the following conditions:
    # Lowest price delivery service price per delivery service
    # Total cart dimensions must be within the delivery service price allocation
    # Total cart price must be within the order constraints of the delivery service
    describe "Calculating the relevant delivery service prices for a cart" do
        let(:cart) { create(:tier_calculated_cart) }

        let!(:delivery_service) { create(:delivery_service, active: true)}
        let!(:delivery_service_price_1) { create(:delivery_service_price, active: true, min_weight: '0', max_weight: '26.75', min_length: '0', max_length: '103.23', min_thickness: '0', max_thickness: '22.71', delivery_service_id: delivery_service.id, price: 1.2, code: 'DEL1') }
        let!(:delivery_service_price_2) { create(:delivery_service_price, active: true, min_weight: '0', max_weight: '18.75', min_length: '0', max_length: '119.23', min_thickness: '0', max_thickness: '49.90', delivery_service_id: delivery_service.id, price: 3.44, code: 'DEL2') }
        let!(:delivery_service_price_3) { create(:delivery_service_price, active: true, min_weight: '22.67', max_weight: '46.75', min_length: '66.82', max_length: '201.45', min_thickness: '12.33', max_thickness: '52.62', delivery_service_id: delivery_service.id, price: 23.24, code: 'DEL3') }

        let!(:delivery_service_2) { create(:delivery_service, active: true, order_price_maximum: 20)}
        let!(:delivery_service_price_4) { create(:delivery_service_price, active: true, min_weight: '0', max_weight: '34.75', min_length: '0', max_length: '1003.23', min_thickness: '0', max_thickness: '55.71', delivery_service_id: delivery_service_2.id, code: 'DEL4') }

        let!(:delivery_service_3) { create(:delivery_service, active: true)}
        let!(:delivery_service_price_5) { create(:delivery_service_price, active: true, min_weight: '0', max_weight: '34.75', min_length: '0', max_length: '1003.23', min_thickness: '0', max_thickness: '55.71', delivery_service_id: delivery_service_3.id, code: 'DEL5') }
        it "should return an array of available delivery service prices, taking into consideration cart dimensions and cart total price" do
            expect(cart.calculate_delivery_services(Store.tax_rate)).to eq [delivery_service_price_1.id, delivery_service_price_5.id]
        end
    end

    describe "During a daily scheduled task" do

        context "if the carts are more than 12 hours old" do
            let!(:cart_1) { create(:cart, updated_at: 11.hours.ago) }
            let!(:cart_2) { create(:cart, updated_at: 13.hours.ago) }
            let!(:cart_3) { create(:cart, updated_at: 28.hours.ago) }

            it "should select the correct carts" do
                expect(Cart.clear_carts).to match_array([cart_2, cart_3])
            end

            it "should remove the carts" do
                expect{
                    Cart.clear_carts
                }.to change(Cart, :count).by(-2)
            end
        end
    end
end
