/*
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"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"sort"
	"strconv"
	"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 = "+18007897890"
	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
}

// InitHTTPConnection creates and returns a new HTTPConnection object
// with a given server address and username/password.
func InitHTTPConnection(serverAddr string, usernamePassword string) *HTTPConnection {
	return &HTTPConnection{
		client:      &http.Client{Timeout: time.Duration(1 * time.Second)},
		credentials: "Basic " + base64.StdEncoding.EncodeToString([]byte(usernamePassword)),
		marshaler:   &jsonpb.Marshaler{OrigName: true},
		// TODO(wsilberm): Use https
		baseURL: "http://" + serverAddr,
	}
}

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")

	// See if we get a response.
	_, err := http.Get(conn.getURL(""))
	if err != nil {
		return fmt.Errorf("could not complete health check: %v", err)
	}
	log.Println("health check success!")
	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) (*http.Response, 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, Request %v\n", rpcName, time.Now().UTC().Format(time.RFC850), httpReq)

	httpResp, err := conn.client.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("invalid response. %s yielded error: %v", rpcName, err)
	}
	return httpResp, nil
}

// CheckAvailability beforms 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)
	}
	defer httpResp.Body.Close()
	var resp mpb.CheckAvailabilityResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return fmt.Errorf("CheckAvailability: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("CheckAvailability Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())

	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)
	}
	defer httpResp.Body.Close()
	var resp mpb.CreateBookingResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return nil, fmt.Errorf("CreateBooking: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("CreateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
	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)
	}
	defer idemHTTPResp.Body.Close()
	var idemResp mpb.CreateBookingResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return nil, fmt.Errorf("CreateBooking idem: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("Idempotency check -- Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), idemResp.String())
	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) {
	var out Bookings
	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)
	}
	defer httpResp.Body.Close()
	var resp mpb.ListBookingsResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return nil, fmt.Errorf("ListBookings: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("ListBookings Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
	gB := Bookings(resp.GetBookings())
	if len(gB) != len(tB) {
		return out, fmt.Errorf("number of bookings differ, ListBookings invalid. Got: %d, Want: %d. Abandoning all bookings from this flow", len(gB), len(tB))
	}

	sort.Sort(gB)
	sort.Sort(tB)
	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])
	}

	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)
	}
	defer httpResp.Body.Close()
	var resp mpb.GetBookingStatusResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return fmt.Errorf("GetBookingsStatus: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("GetBookingStatus Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
	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(b *mpb.Booking, conn *HTTPConnection) error {
	b.Status = mpb.BookingStatus_CANCELED
	reqPB := &mpb.UpdateBookingRequest{
		Booking: b,
	}
	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)
	}
	defer httpResp.Body.Close()
	var resp mpb.UpdateBookingResponse
	if err := jsonpb.Unmarshal(httpResp.Body, &resp); err != nil {
		return fmt.Errorf("CancelBooking: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("UpdateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
	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)
	}
	slot := newBooking.GetSlot()

	// New slot.
	lastAvailability := slots[len(slots)-1]
	slot.StartSec = lastAvailability.GetStartSec()
	slot.DurationSec = lastAvailability.GetDurationSec()

	reqPB := &mpb.UpdateBookingRequest{
		Booking: newBooking,
	}
	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)
	defer updateHTTPResp.Body.Close()
	var resp mpb.CreateBookingResponse
	if err := jsonpb.Unmarshal(updateHTTPResp.Body, &resp); err != nil {
		return fmt.Errorf("Rescheduling UpdateBooking: Could not parse HTTP response to pb3: %v", err)
	}

	log.Printf("UpdateBooking Response. Received(unix): %s, Response %s", time.Now().UTC().Format(time.RFC850), resp.String())
	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(), conn)
}
