/*
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/google/go-cmp/cmp"
	"github.com/maps-booking-v3/utils"

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

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
// will return all slots with a valid return.
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
}

// 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)
	}

	// Price is difficult to verify without knowing aggregator specific taxes/fees. We only check that it is present.
	if resp.GetFeesAndTaxes() == nil || cmp.Diff(fpb.Price{}, *resp.GetFeesAndTaxes(), cmp.Comparer(proto.Equal)) == "" {
		return fmt.Errorf("invalid response. CheckOrderFulfillability.FeesAndTaxes must be populated. Offending response: %v", resp)
	}

	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
}
