/*
Copyright 2017 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package api contains validation wrappers over BookingService endpoints.
package api

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/google/go-cmp/cmp"
	"github.com/maps-booking-v3/utils"

	fpb "github.com/maps-booking-v3/feeds"
	mpb "github.com/maps-booking-v3/v3"
	wpb "github.com/maps-booking-v3/waitlist"
)

const (
	userID    = "0"
	firstName = "Jane"
	lastName  = "Doe"
	telephone = "+1 800-789-7890"
	email     = "test@example.com"
)

// HTTPConnection is a convenience struct for holding connection-related objects.
type HTTPConnection struct {
	client      *http.Client
	credentials string
	marshaler   *jsonpb.Marshaler
	baseURL     string
}

func setupCertConfig(caFile string, fullServerName string) (*tls.Config, error) {
	if caFile == "" {
		return nil, nil
	}
	b, err := ioutil.ReadFile(caFile)
	if err != nil {
		return nil, fmt.Errorf("failed to read root certificates file: %v", err)
	}
	cp := x509.NewCertPool()
	if !cp.AppendCertsFromPEM(b) {
		return nil, errors.New("failed to parse root certificates, please check your roots file (ca_file flag) and try again")
	}
	return &tls.Config{
		RootCAs:    cp,
		ServerName: fullServerName,
	}, nil
}

// InitHTTPConnection creates and returns a new HTTPConnection object
// with a given server address and username/password.
func InitHTTPConnection(serverAddr string, credentialsFile string, caFile string, fullServerName string) (*HTTPConnection, error) {
	// Set up username/password.
	var credentials string
	if credentialsFile != "" {
		data, err := ioutil.ReadFile(credentialsFile)
		if err != nil {
			return nil, err
		}
		credentials = "Basic " + base64.StdEncoding.EncodeToString([]byte(strings.Replace(string(data), "\n", "", -1)))
	}
	config, err := setupCertConfig(caFile, fullServerName)
	if err != nil {
		return nil, err
	}
	protocol := "http"
	if config != nil {
		protocol = "https"
	}
	return &HTTPConnection{
		client: &http.Client{
			Timeout:   10 * time.Second,
			Transport: &http.Transport{TLSClientConfig: config},
		},
		credentials: credentials,
		marshaler:   &jsonpb.Marshaler{OrigName: true},
		baseURL:     protocol + "://" + serverAddr,
	}, nil
}

func (h HTTPConnection) getURL(rpcName string) string {
	if rpcName != "" {
		return h.baseURL + "/v3/" + rpcName
	}
	return h.baseURL
}

// Bookings is a convenience type for a booking array.
type Bookings []*mpb.Booking

func (b Bookings) Len() int {
	return len(b)
}

func (b Bookings) Less(i, j int) bool {
	return b[i].GetBookingId() < b[j].GetBookingId()
}

func (b Bookings) Swap(i, j int) {
	b[i], b[j] = b[j], b[i]
}

// HealthCheck performs a health check.
func HealthCheck(conn *HTTPConnection) error {
	utils.LogFlow("Health Check", "Start")
	defer utils.LogFlow("Health Check", "End")

	httpReq, err := http.NewRequest("GET", conn.getURL("HealthCheck"), nil)
	httpReq.Header.Set("Authorization", conn.credentials)

	// See if we get a response.
	resp, err := conn.client.Do(httpReq)
	if err != nil {
		return fmt.Errorf("Health check failed to connect to server: %v", err)
	} else if resp.StatusCode != 200 {
		return fmt.Errorf("Health check returned unhealthy status: %s", resp.Status)
	}
	log.Printf("health check success! Got status: %s", resp.Status)
	return nil
}

// sendRequest sets up and sends the relevant HTTP request to the server and returns the HTTP response.
func sendRequest(rpcName string, req string, conn *HTTPConnection) (string, error) {
	httpReq, err := http.NewRequest("POST", conn.getURL(rpcName), bytes.NewBuffer([]byte(req)))
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", conn.credentials)
	log.Printf("%v Request. Sent(unix): %s, Url: %v, Method: %v, Header: %v, Body: %v\n", rpcName, time.Now().UTC().Format(time.RFC850), httpReq.URL, httpReq.Method, httpReq.Header, httpReq.Body)

	httpResp, err := conn.client.Do(httpReq)
	if err != nil {
		return "", fmt.Errorf("invalid response. %s yielded error: %v", rpcName, err)
	}
	defer httpResp.Body.Close()
	bodyBytes, err := ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return "", fmt.Errorf("Could not read http response body")
	}
	bodyString := string(bodyBytes)
	log.Printf("%v Response. Received(unix): %s, Response %v\n", rpcName, time.Now().UTC().Format(time.RFC850), bodyString)
	return bodyString, nil
}

// CheckAvailability performs a maps booking availability check on all supplied availability slots. This function
// returns any errors when trying to call the CheckAvailability RPC.
func CheckAvailability(a *fpb.Availability, conn *HTTPConnection) error {
	slot, err := utils.BuildSlotFrom(a)
	if err != nil {
		return fmt.Errorf("unable to build request for check availability flow. err: %v, availability record: %v", err, a.String())
	}
	reqPB := &mpb.CheckAvailabilityRequest{
		Slot: slot,
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("CheckAvailability", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. CheckAvailability yielded error: %v", err)
	}
	var resp mpb.CheckAvailabilityResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("CheckAvailability: Could not parse HTTP response to pb3: %v", err)
	}

	if diff := cmp.Diff(resp.GetSlot(), slot, cmp.Comparer(proto.Equal)); diff != "" {
		return fmt.Errorf("invalid response. CheckAvailability slots differ (-got +want)\n%s", diff)
	}

	if resp.GetCountAvailable() == 0 {
		return errors.New("no count available in response")
	}

	return nil
}

// BatchAvailabilityLookup performs a maps booking batch availability lookup on all supplied availability slots. This function
// returns any errors when trying to call the BatchAvailabilityLookup RPC.
func BatchAvailabilityLookup(av []*fpb.Availability, conn *HTTPConnection) error {
	reqPB, err := utils.BuildBatchAvailabilityLookupRequestFrom(av)
	if err != nil {
		return fmt.Errorf("unable to build request for batch availability lookup flow. err: %v, availability records: %v", err, av)
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("BatchAvailabilityLookup", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. BatchAvailabilityLookup yielded error: %v", err)
	}
	var resp mpb.BatchAvailabilityLookupResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("BatchAvailabilityLookup: Could not parse HTTP response to pb3: %v", err)
	}
	if len(resp.GetSlotTimeAvailability()) != len(reqPB.GetSlotTime()) {
		return fmt.Errorf("invalid response. BatchAvailabilityLookup response.size and request.size differ: %v vs %v", len(resp.GetSlotTimeAvailability()), len(reqPB.GetSlotTime()))
	}
	diffCount := 0
	for i := 0; i < len(reqPB.GetSlotTime()); i++ {
		slotTimeReq := reqPB.GetSlotTime()[i]
		slotTimeResp := resp.GetSlotTimeAvailability()[i].GetSlotTime()
		if diff := cmp.Diff(slotTimeReq, slotTimeResp, cmp.Comparer(proto.Equal)); diff != "" {
			log.Printf("Slot %v differs: req=%v, resp=%v", i, slotTimeReq, slotTimeResp)
			diffCount++
		}
	}
	if diffCount > 0 {
		return fmt.Errorf("invalid response. Found %v diffs", diffCount)
	}
	return nil
}

// CreateBooking attempts to create bookings from availability slots.
func CreateBooking(a *fpb.Availability, conn *HTTPConnection) (*mpb.Booking, error) {
	slot, err := utils.BuildSlotFrom(a)
	if err != nil {
		return nil, fmt.Errorf("unable to build request for check availability flow. err: %v, availability record: %v", err, a.String())
	}

	gen := rand.New(rand.NewSource(time.Now().UnixNano()))
	// Lease currently unsupported.
	reqPB := &mpb.CreateBookingRequest{
		Slot: slot,
		UserInformation: &mpb.UserInformation{
			UserId:     userID,
			GivenName:  firstName,
			FamilyName: lastName,
			Telephone:  telephone,
			Email:      email,
		},
		PaymentInformation: &mpb.PaymentInformation{
			PrepaymentStatus: mpb.PrepaymentStatus_PREPAYMENT_NOT_PROVIDED,
		},
		IdempotencyToken: strconv.Itoa(gen.Intn(1000000)),
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return nil, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}

	httpResp, err := sendRequest("CreateBooking", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. CreateBooking  yielded error: %v", err)
	}
	var resp mpb.CreateBookingResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return nil, fmt.Errorf("CreateBooking: Could not parse HTTP response to pb3: %v", err)
	}

	if resp.GetBookingFailure() != nil {
		return nil, fmt.Errorf("invalid response. CreateBooking failed with booking failure %v", resp.GetBookingFailure())
	}

	b := resp.GetBooking()
	if iE := utils.ValidateBooking(b, &mpb.Booking{
		Slot:               reqPB.GetSlot(),
		UserInformation:    reqPB.GetUserInformation(),
		PaymentInformation: reqPB.GetPaymentInformation(),
	}); iE != nil {
		return nil, fmt.Errorf("invalid response. CreateBooking invalid: %s", iE.Error())
	}

	// Perform idempotency test.
	log.Printf("Idempotency check -- CreateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), reqPB.String())
	idemHTTPResp, err := sendRequest("CreateBooking", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. Idempotency check yielded error: %v", err)
	}
	var idemResp mpb.CreateBookingResponse
	if err := jsonpb.UnmarshalString(idemHTTPResp, &idemResp); err != nil {
		return nil, fmt.Errorf("CreateBooking idem: Could not parse HTTP response to pb3: %v", err)
	}

	if diff := cmp.Diff(idemResp, resp); diff != "" {
		return b, fmt.Errorf("Idempotency check invalid (-got +want)\n%s", diff)
	}

	return b, nil
}

// ListBookings calls the maps booking ListBookings rpc and compares the return with all input bookings.
func ListBookings(tB Bookings, conn *HTTPConnection) (Bookings, error) {
	reqPB := &mpb.ListBookingsRequest{
		UserId: userID,
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return nil, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("ListBookings", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. ListBookings yielded error: %v. Abandoning all booking from this flow", err)
	}
	var resp mpb.ListBookingsResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return nil, fmt.Errorf("ListBookings: Could not parse HTTP response to pb3: %v", err)
	}

	gB := Bookings(resp.GetBookings())
	if len(tB) == 0 {
		log.Printf("ListBookings returning %d found bookings", len(gB))
		return gB, nil
	}
	if len(gB) != len(tB) {
		log.Printf("ListBookings number of bookings differed unexpectedly. Got: %d, Want: %d.", len(gB), len(tB))
	}
	sort.Sort(gB)
	sort.Sort(tB)
	var out Bookings
	for i := 0; i < len(tB); i++ {
		if iE := utils.ValidateBooking(gB[i], tB[i]); iE != nil {
			log.Printf("ListBookings invalid, %s, abandoning slot %d/%d", iE.Error(), i, len(tB))
			continue
		}
		out = append(out, tB[i])
	}
	log.Printf("ListBookings returning %d bookings", len(out))
	return out, nil
}

// GetBookingStatus checks that all input bookings are in an acceptable state.
func GetBookingStatus(b *mpb.Booking, conn *HTTPConnection) error {
	reqPB := &mpb.GetBookingStatusRequest{
		BookingId: b.GetBookingId(),
	}

	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("GetBookingStatus", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. GetBookingStatus yielded error: %v", err)
	}
	var resp mpb.GetBookingStatusResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("GetBookingsStatus: Could not parse HTTP response to pb3: %v", err)
	}

	if diff := cmp.Diff(resp.GetBookingStatus(), mpb.BookingStatus_CONFIRMED); diff != "" {
		return fmt.Errorf("invalid response. BookingStatus differ (-got +want)\n%s", diff)
	}

	return nil
}

// CancelBooking is a clean up method that cancels all supplied bookings.
func CancelBooking(bookingID string, conn *HTTPConnection) error {
	reqPB := &mpb.UpdateBookingRequest{
		Booking: &mpb.Booking{
			BookingId: bookingID,
			Status:    mpb.BookingStatus_CANCELED,
		},
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("UpdateBooking", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. UpdateBooking yielded error: %v", err)
	}
	var resp mpb.UpdateBookingResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("CancelBooking: Could not parse HTTP response to pb3: %v", err)
	}

	if iE := utils.ValidateBooking(resp.GetBooking(), reqPB.GetBooking()); iE != nil {
		return fmt.Errorf("invalid response. UpdateBooking: %s", iE.Error())
	}
	return nil
}

// Rescheduling will attempt to create a booking, update the booking, then cancel.
func Rescheduling(av []*fpb.Availability, conn *HTTPConnection) error {
	var slots []*fpb.Availability
	for _, v := range utils.BuildMerchantServiceMap(av) {
		// Need at least two slots for reschedule.
		if len(v) <= 1 {
			continue
		}
		slots = v
		break
	}

	if len(slots) == 0 {
		return errors.New("no suitable availability for rescheduling flow. exiting")
	}
	// Book first slot.
	newBooking, err := CreateBooking(slots[0], conn)
	if err != nil {
		return fmt.Errorf("could not complete booking, abandoning rescheduling flow: %v", err)
	}

	// New slot.
	lastAvailability := slots[len(slots)-1]

	reqPB := &mpb.UpdateBookingRequest{
		Booking: &mpb.Booking{
			BookingId: newBooking.GetBookingId(),
			Slot: &mpb.Slot{
				StartSec:    lastAvailability.GetStartSec(),
				DurationSec: lastAvailability.GetDurationSec(),
			},
		},
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Rescheduling UpdateBooking: Could not convert pb3 to json: %v", reqPB)
	}
	updateHTTPResp, err := sendRequest("UpdateBooking", req, conn)
	var resp mpb.CreateBookingResponse
	if err := jsonpb.UnmarshalString(updateHTTPResp, &resp); err != nil {
		return fmt.Errorf("Rescheduling UpdateBooking: Could not parse HTTP response to pb3: %v", err)
	}

	// Update slot before performing diff.
	newBooking.GetSlot().StartSec = lastAvailability.GetStartSec()
	newBooking.GetSlot().DurationSec = lastAvailability.GetDurationSec()

	if iE := utils.ValidateBooking(resp.GetBooking(), newBooking); iE != nil {
		return fmt.Errorf("invalid response. UpdateBooking: %s, abandoning slot 1/1", iE.Error())
	}
	return CancelBooking(resp.GetBooking().GetBookingId(), conn)
}

// CheckOrderFulfillability attempts to send a CheckOrderFulfillabilityRequest
// to the connection endpoint and diff the results with what are expected.
func CheckOrderFulfillability(merchantID string, lineItems []*mpb.LineItem, conn *HTTPConnection) error {
	reqPB := &mpb.CheckOrderFulfillabilityRequest{
		MerchantId: merchantID,
		Item:       lineItems,
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("CheckOrderFulfillability", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. CheckOrderFulfillability yielded error: %v", err)
	}
	var resp mpb.CheckOrderFulfillabilityResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("CheckOrderFulfillability: Could not parse HTTP response to pb3: %v", err)
	}

	orderFulfillability := resp.GetFulfillability()
	// TODO(ccawdrey): Add validation cases for other OrderFulFillability enums.
	if diff := cmp.Diff(orderFulfillability.GetResult(), mpb.OrderFulfillability_CAN_FULFILL); diff != "" {
		return fmt.Errorf("invalid response. CheckOrderFulfillability.Fulfillability.OrderFulfillabilityResult differ (-got +want)\n%s", diff)
	}
	if orderFulfillability.GetUnfulfillableReason() != "" {
		return errors.New("invalid response. CheckOrderFulfillability.UnfulfillableReason should be empty")
	}

	var respLineItems []*mpb.LineItem
	for _, lineItemFulfillability := range orderFulfillability.GetItemFulfillability() {
		if diff := cmp.Diff(lineItemFulfillability.GetResult(), mpb.LineItemFulfillability_CAN_FULFILL); diff != "" {
			return fmt.Errorf("invalid response. CheckOrderFulfillability.Fulfillability.ItemFulfillability.Result for LineItem %v -- differ (-got +want)\n%s", lineItemFulfillability.GetItem(), diff)
		}
		if lineItemFulfillability.GetUnfulfillableReason() != "" {
			return errors.New("invalid response. CheckOrderFulfillability.Fulfillability.ItemFulfillability.UnfulfillableReason should be empty")
		}

		respLineItems = append(respLineItems, lineItemFulfillability.GetItem())
	}

	if err = utils.ValidateLineItems(respLineItems, lineItems, false); err != nil {
		return fmt.Errorf("invalid response. CheckOrderFulfillability %v", err)
	}

	return nil
}

// CreateOrder will attempt to build an order from a merchant id and array of line orders.
func CreateOrder(merchantID string, lineItems []*mpb.LineItem, conn *HTTPConnection) (*mpb.Order, error) {
	gen := rand.New(rand.NewSource(time.Now().UnixNano()))

	reqOrder := &mpb.Order{
		UserInformation: &mpb.UserInformation{
			UserId:     userID,
			GivenName:  firstName,
			FamilyName: lastName,
			Telephone:  telephone,
			Email:      email,
		},
		PaymentInformation: &mpb.PaymentInformation{
			PrepaymentStatus: mpb.PrepaymentStatus_PREPAYMENT_NOT_PROVIDED,
		},
		MerchantId: merchantID,
		Item:       lineItems,
	}
	reqPB := &mpb.CreateOrderRequest{
		Order:            reqOrder,
		IdempotencyToken: strconv.Itoa(gen.Intn(1000000)),
	}

	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return nil, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("CreateOrder", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. CreateOrder yielded error: %v", err)
	}
	var resp mpb.CreateOrderResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return nil, fmt.Errorf("CreateOrder: Could not parse HTTP response to pb3: %v", err)
	}

	if resp.GetOrderFailure() != nil {
		return nil, fmt.Errorf("invalid response. CreateOrder contains OrderFailure for request %v", reqPB)
	}

	if err = utils.ValidateOrder(*resp.GetOrder(), *reqOrder); err != nil {
		return nil, fmt.Errorf("invalid response. CreateOrder %v", err)
	}

	// Perform idempotency test.
	log.Printf("Idempotency check")
	idemHTTPResp, err := sendRequest("CreateOrder", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. Idempotency check yielded error: %v", err)
	}
	var idemResp mpb.CreateOrderResponse
	if err := jsonpb.UnmarshalString(idemHTTPResp, &idemResp); err != nil {
		return nil, fmt.Errorf("CreateOrder idem: Could not parse HTTP response to pb3: %v", err)
	}

	if idemResp.GetOrderFailure() != nil {
		return nil, errors.New("Idempotency check invalid. CreateOrder contains OrderFailure")
	}
	if err = utils.ValidateOrder(*idemResp.GetOrder(), *resp.GetOrder()); err != nil {
		return nil, fmt.Errorf("Idempotency check invalid  %v", err)
	}

	return resp.GetOrder(), nil
}

func sendListOrdersRequest(reqPB *mpb.ListOrdersRequest, conn *HTTPConnection) (mpb.ListOrdersResponse, error) {
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return mpb.ListOrdersResponse{}, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("ListOrders", req, conn)
	if err != nil {
		return mpb.ListOrdersResponse{}, fmt.Errorf("invalid response. ListOrders yielded error: %v", err)
	}
	var resp mpb.ListOrdersResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return resp, fmt.Errorf("ListOrders: Could not parse HTTP response to pb3: %v", err)
	}

	return resp, nil
}

// ListOrders first checks that the number and contents of the server's order state
// are consistent with what the test client assumes is present.
func ListOrders(orders []*mpb.Order, conn *HTTPConnection) error {
	if len(orders) == 0 {
		return errors.New("at least one order must be present for ListOrders to succeed")
	}

	// UserId check first.
	reqPB := &mpb.ListOrdersRequest{
		Ids: &mpb.ListOrdersRequest_UserId{userID},
	}
	respUser, err := sendListOrdersRequest(reqPB, conn)
	if err != nil {
		return err
	}
	if err = utils.ValidateOrders(respUser.GetOrder(), orders); err != nil {
		return fmt.Errorf("invalid response. ListOrders %v for request %v", err, reqPB)
	}

	// Still here? OrderId check.
	reqPB.Reset()
	var orderIDs mpb.ListOrdersRequest_OrderIds
	for _, order := range orders {
		orderIDs.OrderId = append(orderIDs.OrderId, order.GetOrderId())
	}
	reqPB.Ids = &mpb.ListOrdersRequest_OrderIds_{&orderIDs}

	respOrder, err := sendListOrdersRequest(reqPB, conn)
	if err != nil {
		return err
	}
	if err = utils.ValidateOrders(respOrder.GetOrder(), orders); err != nil {
		return fmt.Errorf("invalid response. ListOrders %v for request %v", err, reqPB)
	}

	return nil
}

// BatchGetWaitEstimates calls the partners API and verifies the returned WaitEstimates.
func BatchGetWaitEstimates(s *fpb.Service, conn *HTTPConnection) error {
	rules := s.GetWaitlistRules()

	ps := make([]int32, rules.GetMaxPartySize()-rules.GetMinPartySize())
	for i := range ps {
		ps[i] = rules.GetMinPartySize() + int32(i)
	}
	reqPB := &wpb.BatchGetWaitEstimatesRequest{
		MerchantId: s.GetMerchantId(),
		ServiceId:  s.GetServiceId(),
		PartySize:  ps,
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("BatchGetWaitEstimates", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. BatchGetWaitEstimates yielded error: %v", err)
	}
	var resp wpb.BatchGetWaitEstimatesResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("BatchGetWaitEstimates: Could not parse HTTP response to pb3: %v", err)
	}

	if resp.GetWaitlistStatus() == wpb.WaitlistStatus_WAITLIST_STATUS_UNSPECIFIED {
		return errors.New("BatchGetWaitEstimates: waitlist status was not specified in response")
	} else if resp.GetWaitlistStatus() != wpb.WaitlistStatus_OPEN {
		// Waitlist is closed. Wait estimate should not be provided.
		if len(resp.GetWaitEstimate()) > 0 {
			return errors.New("BatchGetWaitEstimates: wait estimate must not be provided when waitlist is closed")
		}
	}

	// Waitlist status is OPEN
	for _, we := range resp.GetWaitEstimate() {
		if err := utils.ValidateWaitEstimate(we); err != nil {
			return fmt.Errorf("BatchGetWaitEstimates invalid, %s, service id: %s",
				err.Error(), s.GetServiceId())
		} else if we.GetPartySize() > rules.GetMaxPartySize() ||
			we.GetPartySize() < rules.GetMinPartySize() {
			return fmt.Errorf("batchGetWaitEstimates: Party size outside of min/max for service id: %s."+
				"returned party size: %d, min party size: %d, max party size: %d",
				s.GetServiceId(), we.GetPartySize(), rules.GetMinPartySize(), rules.GetMaxPartySize())
		}
	}
	return nil
}

// CreateWaitlistEntry attempts to create waitlist entries from a service.
// The max party size listed for the service's waitlist rules is used for
// the waitlist entry's party size.
func CreateWaitlistEntry(s *fpb.Service, conn *HTTPConnection) (string, error) {
	gen := rand.New(rand.NewSource(time.Now().UnixNano()))

	reqPB := &wpb.CreateWaitlistEntryRequest{
		MerchantId: s.GetMerchantId(),
		ServiceId:  s.GetServiceId(),
		PartySize:  s.GetWaitlistRules().GetMaxPartySize(),
		UserInformation: &wpb.UserInformation{
			UserId:     userID,
			GivenName:  firstName,
			FamilyName: lastName,
			Telephone:  telephone,
			Email:      email,
		},
		IdempotencyToken: strconv.Itoa(gen.Intn(1000000)),
	}
	if s.GetWaitlistRules().GetSupportsAdditionalRequest() {
		reqPB.AdditionalRequest = "test additional request"
	}
	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return "", fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}

	httpResp, err := sendRequest("CreateWaitlistEntry", req, conn)
	if err != nil {
		return "", fmt.Errorf("invalid response. CreateWaitlistEntry  yielded error: %v", err)
	}
	var resp wpb.CreateWaitlistEntryResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return "", fmt.Errorf("CreateWaitlistEntry: Could not parse HTTP response to pb3: %v", err)
	}

	if resp.GetWaitlistBusinessLogicFailure() != nil {
		return "", fmt.Errorf("invalid response. CreateWaitlistEntry failed with business logic failure %v",
			resp.GetWaitlistBusinessLogicFailure())
	}

	if resp.GetWaitlistEntryId() == "" {
		return "", fmt.Errorf("invalid response. CreateWaitlistEntry missing waitlist entry id for service: %s",
			s.GetServiceId())
	}

	// Perform idempotency test.
	log.Printf("Idempotency check -- CreateWaitlistEntry Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), reqPB.String())
	idemHTTPResp, err := sendRequest("CreateWaitlistEntry", req, conn)
	if err != nil {
		return "", fmt.Errorf("invalid response. Idempotency check yielded error: %v", err)
	}
	var idemResp wpb.CreateWaitlistEntryResponse
	if err := jsonpb.UnmarshalString(idemHTTPResp, &idemResp); err != nil {
		return "", fmt.Errorf("CreateWaitlistEntry idem: Could not parse HTTP response to pb3: %v", err)
	}

	if diff := cmp.Diff(idemResp, resp); diff != "" {
		return "", fmt.Errorf("Idempotency check invalid (-got +want)\n%s for service: %s", diff, s.GetServiceId())
	}

	return resp.GetWaitlistEntryId(), nil
}

// GetWaitlistEntry retrieves and validates the booking for the specified
// waitlist entry id.
func GetWaitlistEntry(id string, conn *HTTPConnection) (*wpb.WaitlistEntry, error) {
	reqPB := &wpb.GetWaitlistEntryRequest{
		WaitlistEntryId: id,
	}

	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return nil, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest("GetWaitlistEntry", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. GetWaitlistEntry yielded error: %v", err)
	}
	var resp wpb.GetWaitlistEntryResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return nil, fmt.Errorf("GetWaitlistEntry: Could not parse HTTP response to pb3: %v", err)
	}

	if iE := utils.ValidateWaitlistEntry(resp.GetWaitlistEntry()); iE != nil {
		return nil, fmt.Errorf("invalid response. GetWaitlistEntry: %s", iE.Error())
	}

	return resp.GetWaitlistEntry(), nil
}

// DeleteWaitlistEntry makes a request to delete the waitlist entry.
func DeleteWaitlistEntry(id string, conn *HTTPConnection) error {
	reqPB := &wpb.DeleteWaitlistEntryRequest{
		WaitlistEntryId: id,
	}

	req, err := conn.marshaler.MarshalToString(reqPB)
	if err != nil {
		return fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}

	httpResp, err := sendRequest("DeleteWaitlistEntry", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. DeleteWaitlistEntry yielded error: %v", err)
	}

	var resp empty.Empty
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return fmt.Errorf("DeleteWaitlistEntry: Could not parse HTTP response to pb3: %v. Body should be: {}", err)
	}

	return nil
}
