public async Task <IActionResult> AddToBasket(string offeringID, [FromHeader] string authorization, [FromQuery] int qty = 0)
        {
            // make sure an offering_key was sent - can't do anything without it
            if (offeringID == null)
            {
                return(BadRequest(new BadRequestError("no offering_key sent.")));
            }

            // make sure the quantity is greater than zero
            if (qty <= 0)
            {
                return(BadRequest(new BadRequestError("Quantity is zero")));
            }

            // get the user_id
            var ID = GetID();

            if (ID == null)
            {
                return(BadRequest(new BadRequestError("user_id not found.")));
            }

            // attempt to retreive the users Basket document
            var doc = await _bucket.GetAsync <BasketDisc>(ID);

            int        newOffering = 0;
            BasketDisc userDoc     = null;

            // check to see if a document was retreived, need to create a new one if it wasn't
            if (doc.Success)
            {
                userDoc = doc.Value;

                // documents are persistent once they have been created so update the doc with the new time if total_items is zero
                if (userDoc.total_items == 0)
                {
                    userDoc.Date = DateTimeOffset.Now.ToUnixTimeSeconds();
                }

                // check to see if the offeringID sent in the route is already in the OfferingsDisc array
                if (userDoc.OfferingsDisc.Exists(i => i.Offering_key == offeringID))
                {
                    OfferingsDisc offer = userDoc.OfferingsDisc.Find(i => i.Offering_key == offeringID);

                    // find the index of where the element with offeringID is located in the array
                    var index = userDoc.OfferingsDisc.IndexOf(offer, 0);

                    // update all the information about the offering in the basket
                    userDoc.OfferingsDisc[index].Quantity += qty;
                    userDoc.total_cost           = (Convert.ToDecimal(userDoc.total_cost) - Convert.ToDecimal(offer.totalOfferingCost)).ToString();
                    userDoc.OfferingsDisc[index] = CalcOfferingCost(userDoc.OfferingsDisc[index]);
                    userDoc.total_cost           = (Convert.ToDecimal(userDoc.total_cost) + Convert.ToDecimal(offer.totalOfferingCost)).ToString();
                }
                else // if the offeringID isn't in the array set the newOffering flag (used later)
                {
                    newOffering = 1;
                }
            }
            // if there isn't already a Basket document for the user or the newOffering flag is set
            if (!doc.Success || newOffering == 1)
            {
                // split the authorization header string to remove 'Bearer' and isolate the JWT token
                string[] auth = authorization.Split(' ');
                // use the GetOffering() function to send the HTTP request to the CatalogApi to get the information about the offering being added
                HttpResponseMessage httpResponse = await GetOffering(auth[1], "http://localhost:7000/catalog-api/products/disc/singleOffering/" + offeringID);

                // make sure the HTTP response from the CatalogApi was successful
                if (!httpResponse.IsSuccessStatusCode)
                {
                    return(BadRequest(new BadRequestError(httpResponse.StatusCode.ToString() + " HttpRequest Failed.")));
                }

                // read the response as a type OfferingsDisc (what we will be adding to the Basket document)
                OfferingsDisc offering = await httpResponse.Content.ReadAsAsync <OfferingsDisc>();

                offering.Quantity = qty;
                BasketDisc basket = null;

                // check to see if the discount type is a BULK_DISCOUNT, need to use interproces communication again to get the tiers information about it
                if (offering.Type != "BULK_DISCOUNT")
                {
                    offering = CalcOfferingCost(offering);
                }
                else if (offering.Type == "BULK_DISCOUNT")
                {
                    // get the BULK_DISCOUNT tiers information
                    httpResponse = await GetOffering(auth[1], "http://localhost:7000/catalog-api/products/disc/getDiscount/" + offering.Discount_key);

                    if (!httpResponse.IsSuccessStatusCode)
                    {
                        return(BadRequest(new BadRequestError(httpResponse.StatusCode.ToString() + " HttpRequest Failed.")));
                    }

                    // use the tiers information to correctly calculate the cost of the offering being added
                    offering.Tiers = new List <Tiers>();
                    offering.Tiers = await httpResponse.Content.ReadAsAsync <List <Tiers> >();

                    offering = CalcOfferingCost(offering);
                }

                // if newOffering is 0 update all the information and insert the Basket document
                if (newOffering == 0)
                {
                    basket               = new BasketDisc();
                    basket.Uid           = Guid.NewGuid();
                    basket.Date          = DateTimeOffset.Now.ToUnixTimeSeconds();
                    basket.total_items   = 1;
                    basket.OfferingsDisc = new List <OfferingsDisc>();
                    basket.OfferingsDisc.Add(offering);
                    basket.total_cost = offering.totalOfferingCost;

                    var res = await _bucket.UpsertAsync(ID, basket);

                    if (!res.Success)
                    {
                        return(BadRequest(new BadRequestError("Failed to add document to database - new basket")));
                    }

                    return(Ok(basket));
                }

                userDoc.total_cost    = (Convert.ToDecimal(userDoc.total_cost) + Convert.ToDecimal(offering.totalOfferingCost)).ToString();
                userDoc.OfferingsDisc = userDoc.OfferingsDisc.Prepend(offering).ToList();
                userDoc.total_items  += 1;
            }

            // insert the Basket document
            var result = await _bucket.UpsertAsync(ID, userDoc);

            if (!result.Success)
            {
                return(BadRequest(new BadRequestError("Failed to add userDoc to database")));
            }

            // reutrn 200 OK, we don't need to return userDoc this was for testing
            return(Ok(userDoc));
        }
        public async Task <IActionResult> AddDocDiscount([FromBody] BasketDisc basket)
        {
            // check if the model binds correctly
            if (ModelState.IsValid)
            {
                // get the users ID from the HttpContext
                var ID = GetID();

                // The ID should never be NULL because they wouldn't have been authorized but checking anyways
                if (ID == null)
                {
                    return(BadRequest(new BadRequestError("user_id not found.")));
                }

                var doc = await _bucket.GetAsync <BasketDisc>(ID); // check to see if a document for the user exists or not

                if (!doc.Success)                                  // if the user doesn't already have a basket document make a new one
                {
                    // check to see if the GUID is set or not
                    if (!basket.Uid.HasValue)
                    {
                        basket.Uid = Guid.NewGuid();
                    }
                    // update the total number of offerings count in the document
                    basket.total_items = basket.OfferingsDisc.Count();
                    // attempt to insert the new document
                    var response = await _bucket.UpsertAsync(ID, basket);

                    // return a BadReuqest if this fails
                    if (!response.Success)
                    {
                        return(BadRequest(basket));
                    }
                    // otherwise return 200 OK
                    return(Ok(response.ToString()));
                }

                BasketDisc userDoc = doc.Value;

                // find if the product offering already exists, if it does replace it with the new one
                if (userDoc.OfferingsDisc.Exists(i => i.Offering_key == basket.OfferingsDisc[0].Offering_key))
                {
                    OfferingsDisc userOffering = userDoc.OfferingsDisc.Find(i => i.Offering_key == basket.OfferingsDisc[0].Offering_key);
                    // get the index of duplicate item currently stored in the basket doc if it eists
                    var index = userDoc.OfferingsDisc.IndexOf(userOffering, 0);

                    // if there is a duplicate item add the quantities together
                    if (index != -1)
                    {
                        userDoc.OfferingsDisc[index].Quantity += basket.OfferingsDisc[0].Quantity;
                    }
                }
                else // if there isn't a duplicate item insert the new item being added at the beginning of the list
                {
                    userDoc.OfferingsDisc = userDoc.OfferingsDisc.Prepend(basket.OfferingsDisc[0]).ToList();
                }

                // update the total count of the number of offerings stored in the document
                userDoc.total_items = userDoc.OfferingsDisc.Count();

                // attempt to insert the updated document into the Basket bucket
                var result = await _bucket.UpsertAsync(ID, userDoc);

                // if the upsert fails return a bad request
                if (!result.Success)
                {
                    return(BadRequest(basket));
                }

                // if document was successfully replaced return 200 OK
                return(Ok(basket));
            }

            return(Conflict());
        }