require 'dry/struct/with_setters'

require "pwinty/shipping_info"

module Pwinty
    class Order < Pwinty::Base
        include Dry::Struct::Setters
        include Dry::Struct::Setters::MassAssignment

        attribute :id, Types::Integer
        attribute :address1, Types::String.optional
        attribute :address2, Types::String.optional
        attribute :postalOrZipCode, Types::String.optional
        attribute :countryCode, Types::String
        attribute :addressTownOrCity, Types::String.optional
        attribute :recipientName, Types::String.optional
        attribute :stateOrCounty, Types::String.optional
        attribute :status, Types::String
        attribute :payment, Types::String
        attribute :paymentUrl, Types::String.optional
        attribute :price, Types::Integer
        attribute :shippingInfo, Pwinty::ShippingInfo
        attribute :images, Types::Array.of(Pwinty::Image)
        attribute :merchantOrderId, Types::String.optional
        attribute :preferredShippingMethod, Types::String
        attribute :mobileTelephone, Types::String.optional
        attribute :created, Types::JSON::DateTime
        attribute :lastUpdated, Types::JSON::DateTime
        attribute :canCancel, Types::Bool
        attribute :canHold, Types::Bool
        attribute :canUpdateShipping, Types::Bool
        attribute :canUpdateImages, Types::Bool
        attribute :errorMessage, Types::String.optional
        attribute :invoiceAmountNet, Types::Integer
        attribute :invoiceTax, Types::Integer
        attribute :invoiceCurrency, Types::String.optional
        attribute :tag, Types::String.optional

        def self.list(page_size=50)
            all_orders = list_each_page(page_size)
            Pwinty.collate_results(all_orders, self)
        end

        def self.list_each_page(page_size, page_start=0, total_orders_count=nil)
            all_orders = []
            while total_orders_count.nil? or all_orders.count < total_orders_count
                response = Pwinty.conn.get("orders?limit=#{page_size}&start=#{page_start}")
                total_orders_count ||= response.body['data']['count']
                all_orders = all_orders + response.body['data']['content']
                page_start = page_start + page_size
            end
            all_orders
        end


        def self.count
            response = Pwinty.conn.get("orders?count=1&offset=0")
            response.body['data']['count']
        end


        def self.create(**args)
            response = Pwinty.conn.post("orders", args)
            new(response.body['data'])
        end

        def self.find(id)
            response = Pwinty.conn.get("orders/#{id}")
            new(response.body['data'])
        end

        def update(**args)
            update_body = self.to_hash.merge(args)
            response = Pwinty.conn.put("orders/#{self.id}/", update_body)
            self.assign_attributes(response.body['data'])
        end

        def submission_status
            response = Pwinty.conn.get("orders/#{id}/SubmissionStatus")
            Pwinty::OrderStatus.new(response.body['data'])
        end

        def submit
            self.update_status 'Submitted'
        end

        def cancel
            self.update_status 'Cancelled'
        end

        def hold
            self.update_status 'AwaitingPayment'
        end

        def add_image image
            images = add_images([image])
            self.images
        end

        def add_images images
            response = Pwinty.conn.post("orders/#{self.id}/images/batch", images)
            images = Pwinty.collate_results(response.body['data']['items'], Pwinty::Image)
            self.images = self.images + images
        end

        protected

        def update_status status
            response = Pwinty.conn.post("orders/#{self.id}/status", {status: status})
            success = response.status == 200
            unless success
                Pwinty.logger.warn response.body['statusTxt']
            end
            success
        end

    end
end