/*
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 (
	"errors"
	"fmt"
	"log"
	"sort"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
	"github.com/google/go-cmp/cmp"
	"github.com/maps-booking/utils"
	"golang.org/x/net/context"
	"google.golang.org/genproto/protobuf/field_mask"
	"google.golang.org/grpc"

	mpb "github.com/maps-booking/bookingservice"
	fpb "github.com/maps-booking/feeds"
	hpb "google.golang.org/grpc/health/grpc_health_v1"
)

const (
	userID    = "0"
	firstName = "Jane"
	lastName  = "Doe"
	telephone = "+18007897890"
	email     = "test@example.com"
	service   = "ext.maps.booking.partner.v2.BookingService"
)

// 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 gRPC health check.
func HealthCheck(ctx context.Context, conn *grpc.ClientConn) error {
	utils.LogFlow("Health Check", "Start")
	defer utils.LogFlow("Health Check", "End")

	healthCli := hpb.NewHealthClient(conn)
	req := &hpb.HealthCheckRequest{Service: service}
	// Ignore cancel. Server will take care of it.
	resp, err := healthCli.Check(ctx, req)
	if err != nil {
		return fmt.Errorf("could not complete health check: %v", err)
	}

	if diff := cmp.Diff(resp.Status, hpb.HealthCheckResponse_SERVING); diff != "" {
		return fmt.Errorf("health check invalid (-got +want)\n%s", diff)
	}
	log.Println("health check success!")
	return 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(ctx context.Context, a *fpb.Availability, c mpb.BookingServiceClient) 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())
	}

	req := &mpb.CheckAvailabilityRequest{
		Slot: slot,
	}

	log.Printf("CheckAvailability Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.CheckAvailability(ctx, req)
	if err != nil {
		return fmt.Errorf("invalid response. CheckAvailability yielded error: %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(), req.GetSlot(), 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(ctx context.Context, a *fpb.Availability, c mpb.BookingServiceClient) (*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())
	}
	// Lease currently unsupported.
	req := &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: utils.BuildIdempotencyToken(a, userID),
	}

	log.Printf("CreateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.CreateBooking(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("invalid response. CreateBooking  yielded error: %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:               req.GetSlot(),
		UserInformation:    req.GetUserInformation(),
		PaymentInformation: req.GetPaymentInformation(),
	}); iE != nil {
		return nil, fmt.Errorf("invalid response. CreateBooking invalid: %s", iE.Error())
	}
	return b, nil
}

// ListBookings calls the maps booking ListBookings rpc and compares the return with all input bookings.
func ListBookings(ctx context.Context, tB Bookings, c mpb.BookingServiceClient) (Bookings, error) {
	var out Bookings
	req := &mpb.ListBookingsRequest{
		UserId: userID,
	}
	log.Printf("ListBookings Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.ListBookings(ctx, req)
	if err != nil {
		return out, fmt.Errorf("invalid response. ListBookings yielded error: %v. Abandoning all booking from this flow", 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(ctx context.Context, b *mpb.Booking, c mpb.BookingServiceClient) error {
	req := &mpb.GetBookingStatusRequest{
		BookingId: b.GetBookingId(),
	}

	log.Printf("GetBookingStatus Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.GetBookingStatus(ctx, req)
	if err != nil {
		return fmt.Errorf("invalid response. GetBookingStatus yielded error: %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(ctx context.Context, b *mpb.Booking, c mpb.BookingServiceClient) error {
	b.Status = mpb.BookingStatus_CANCELED
	req := &mpb.UpdateBookingRequest{
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"status"},
		},
		Booking: b,
	}

	log.Printf("UpdateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.UpdateBooking(ctx, req)
	if err != nil {
		return fmt.Errorf("invalid response. UpdateBooking yielded error: %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(), req.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, av []*fpb.Availability, c mpb.BookingServiceClient) 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, slots[0], c)
	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]
	startTime, err := ptypes.TimestampProto(time.Unix(lastAvailability.GetStartSec(), 0))
	if err != nil {
		return fmt.Errorf("could not complete update, abandoning rescheduling flow: %v", err)
	}
	slot.StartTime = startTime
	slot.Duration = ptypes.DurationProto(time.Duration(lastAvailability.GetDurationSec()) * time.Second)

	req := &mpb.UpdateBookingRequest{
		UpdateMask: &field_mask.FieldMask{
			Paths: []string{"slot.start_time", "slot.duration"},
		},
		Booking: newBooking,
	}

	log.Printf("UpdateBooking Request. Sent(unix): %s, Request %s", time.Now().UTC().Format(time.RFC850), req.String())
	resp, err := c.UpdateBooking(ctx, req)
	if err != nil {
		return fmt.Errorf("invalid response. UpdateBooking yielded error: %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(ctx, resp.GetBooking(), c)
}
