/*
Copyright 2019 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"
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"sort"
	"strconv"
	"strings"
	"time"

	epb "github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"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/v3waitlist"
)

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

type slotKey struct {
	serviceID string
	startSec  int64
}

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 utils.HTTPConnection object
// with a given server address and username/password.
func InitHTTPConnection(serverAddr string, credentialsFile string, caFile string, fullServerName string) (*utils.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 &utils.HTTPConnection{
		Client: &http.Client{
			Transport: &http.Transport{TLSClientConfig: config},
		},
		Credentials: credentials,
		Marshaler:   &jsonpb.Marshaler{OrigName: true},
		BaseURL:     protocol + "://" + serverAddr,
	}, nil
}

// 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(ctx context.Context, logger *log.Logger, conn *utils.HTTPConnection) error {
	utils.LogFlow(logger, "Health Check", "Start")
	defer utils.LogFlow(logger, "Health Check", "End")

	fmt.Println(conn.GetURL("HealthCheck"))
	httpReq, err := http.NewRequest("GET", conn.GetURL("HealthCheck"), nil)
	reqCtx, cancel := context.WithTimeout(ctx, reqTimeout)
	defer cancel()
	httpReq = httpReq.WithContext(reqCtx)
	httpReq.Header.Set("Authorization", conn.Credentials)

	// See if we get a response.
	resp, err := conn.Client.Do(httpReq)
	if err := ctx.Err(); err != nil {
		panic(fmt.Sprintf("Encountered context error: %s", err.Error()))
	}
	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)
	}
	logger.Printf("health check success! Got status: %s", resp.Status)
	return nil
}

func getLogSafeHeader(header http.Header) http.Header {
	logHeader := make(http.Header)
	for k, v := range header {
		if k == "Authorization" {
			logHeader.Set("Authorization", "VALUE REDACTED.")
			continue
		}
		logHeader[k] = v
	}
	return logHeader
}

// sendRequest sets up and sends the relevant HTTP request to the server and returns the HTTP response.
func sendRequest(ctx context.Context, logger *log.Logger, rpcName string, req string, conn *utils.HTTPConnection) (string, error) {
	httpReq, err := http.NewRequest("POST", conn.GetURL(rpcName), bytes.NewBuffer([]byte(req)))
	reqCtx, cancel := context.WithTimeout(ctx, reqTimeout)
	defer cancel()
	httpReq = httpReq.WithContext(reqCtx)
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", conn.Credentials)
	logHeader := getLogSafeHeader(httpReq.Header)
	logger.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, logHeader, httpReq.Body)

	httpResp, err := conn.Client.Do(httpReq)
	if err := ctx.Err(); err != nil {
		panic(fmt.Sprintf("Encountered context error: %s", err.Error()))
	}
	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)
	logger.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(ctx context.Context, logger *log.Logger, a *fpb.Availability, conn *utils.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(ctx, logger, "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
}

// AvailableSlotsFromBAL performs a maps booking batch availability lookup on all supplied availability slots. This function
// returns any errors when trying to call the BatchAvailabilityLookup RPC or returns all slots the aggregator marked as available.
func AvailableSlotsFromBAL(ctx context.Context, logger *log.Logger, av []*fpb.Availability, conn *utils.HTTPConnection) ([]*fpb.Availability, error) {
	var slotMap = make(map[slotKey]*fpb.Availability)
	for _, a := range av {
		slotMap[slotKey{a.ServiceId, a.StartSec}] = a
	}
	reqPB, err := utils.BuildBatchAvailabilityLookupRequestFrom(av)
	if err != nil {
		return nil, 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 nil, fmt.Errorf("Could not convert pb3 to json: %v", reqPB)
	}
	httpResp, err := sendRequest(ctx, logger, "BatchAvailabilityLookup", req, conn)
	if err != nil {
		return nil, fmt.Errorf("invalid response. BatchAvailabilityLookup yielded error: %v", err)
	}
	var resp mpb.BatchAvailabilityLookupResponse
	if err := jsonpb.UnmarshalString(httpResp, &resp); err != nil {
		return nil, fmt.Errorf("BatchAvailabilityLookup: Could not parse HTTP response to pb3: %v", err)
	}
	if len(resp.GetSlotTimeAvailability()) != len(reqPB.GetSlotTime()) {
		return nil, fmt.Errorf("invalid response. BatchAvailabilityLookup response.size and request.size differ: %v vs %v", len(resp.GetSlotTimeAvailability()), len(reqPB.GetSlotTime()))
	}
	diffCount := 0
	var slots []*fpb.Availability
	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 != "" {
			logger.Printf("Slot %v differs: req=%v, resp=%v", i, slotTimeReq, slotTimeResp)
			diffCount++
		}
		if resp.GetSlotTimeAvailability()[i].GetAvailable() {
			slots = append(slots, slotMap[slotKey{slotTimeResp.GetServiceId(), slotTimeResp.GetStartSec()}])
		}
	}
	if diffCount > 0 {
		return nil, fmt.Errorf("invalid response. Found %v diffs", diffCount)
	}
	return slots, nil
}

// CreateBooking attempts to create bookings from availability slots.
func CreateBooking(ctx context.Context, logger *log.Logger, a *fpb.Availability, conn *utils.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(ctx, logger, "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.
	logger.Printf("Idempotency check -- CreateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), reqPB.String())
	idemHTTPResp, err := sendRequest(ctx, logger, "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, cmp.Comparer(proto.Equal)); 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(ctx context.Context, logger *log.Logger, tB Bookings, conn *utils.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(ctx, logger, "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 {
		logger.Printf("ListBookings returning %d found bookings", len(gB))
		return gB, nil
	}
	if len(gB) != len(tB) {
		logger.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 {
			logger.Printf("ListBookings invalid, %s, abandoning slot %d/%d", iE.Error(), i, len(tB))
			continue
		}
		out = append(out, tB[i])
	}
	logger.Printf("ListBookings returning %d bookings", len(out))
	return out, nil
}

// GetBookingStatus checks that all input bookings are in an acceptable state.
func GetBookingStatus(ctx context.Context, logger *log.Logger, b *mpb.Booking, conn *utils.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(ctx, logger, "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)
	}

	// BookingStatus_CONFIRMED is the default case unless the slot is async, in which
	// case the default is BookingStatus_PENDING_MERCHANT_CONFIRMATION.
	wantStatus := mpb.BookingStatus_CONFIRMED
	if b.GetSlot().GetConfirmationMode() == mpb.ConfirmationMode_CONFIRMATION_MODE_ASYNCHRONOUS {
		wantStatus = mpb.BookingStatus_PENDING_MERCHANT_CONFIRMATION
	}
	if diff := cmp.Diff(resp.GetBookingStatus(), wantStatus); diff != "" {
		return fmt.Errorf("invalid response. BookingStatus differs (-got +want)\n%s", diff)
	}

	return nil
}

// CancelBooking is a clean up method that cancels all supplied bookings.
func CancelBooking(ctx context.Context, logger *log.Logger, bookingID string, conn *utils.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(ctx, logger, "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)
	}

	// We only care that the correct booking was cancelled. The rest of the response content
	// is not relevant.
	compareBooking := &mpb.Booking{
		BookingId: resp.GetBooking().GetBookingId(),
		Status:    resp.GetBooking().GetStatus(),
	}
	if iE := utils.ValidateBooking(compareBooking, 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(ctx context.Context, logger *log.Logger, av []*fpb.Availability, conn *utils.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(ctx, logger, 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(ctx, logger, "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(ctx, logger, resp.GetBooking().GetBookingId(), conn)
}

// CheckOrderFulfillability attempts to send a CheckOrderFulfillabilityRequest
// to the connection endpoint and diff the results with what are expected.
func CheckOrderFulfillability(ctx context.Context, logger *log.Logger, merchantID string, lineItems []*mpb.LineItem, conn *utils.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(ctx, logger, "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()
	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(ctx context.Context, logger *log.Logger, merchantID string, lineItems []*mpb.LineItem, conn *utils.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(ctx, logger, "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.
	logger.Printf("Idempotency check")
	idemHTTPResp, err := sendRequest(ctx, logger, "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(ctx context.Context, logger *log.Logger, reqPB *mpb.ListOrdersRequest, conn *utils.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(ctx, logger, "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(ctx context.Context, logger *log.Logger, orders []*mpb.Order, conn *utils.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(ctx, logger, 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(ctx, logger, 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(ctx context.Context, logger *log.Logger, s *fpb.Service, conn *utils.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(ctx, logger, "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(ctx context.Context, logger *log.Logger, s *fpb.Service, conn *utils.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(ctx, logger, "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.
	logger.Printf("Idempotency check -- CreateWaitlistEntry Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), reqPB.String())
	idemHTTPResp, err := sendRequest(ctx, logger, "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, cmp.Comparer(proto.Equal)); 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(ctx context.Context, logger *log.Logger, id string, conn *utils.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(ctx, logger, "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(ctx context.Context, logger *log.Logger, id string, conn *utils.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(ctx, logger, "DeleteWaitlistEntry", req, conn)
	if err != nil {
		return fmt.Errorf("invalid response. DeleteWaitlistEntry yielded error: %v", err)
	}

	var resp epb.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
}
