/*
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 utils contains common BookingService based helper functions.
package utils

import (
	"crypto/sha256"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"os"
	"path"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
	"github.com/google/go-cmp/cmp"

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

const logFile = "http_test_client_log_"

// SlotKey is a struct representing a unique service.
type SlotKey struct {
	MerchantID string
	ServiceID  string
	StaffID    string
	RoomID     string
}

func createLogFile(outPath string) (*os.File, error) {
	var err error
	if outPath == "" {
		outPath, err = os.Getwd()
		if err != nil {
			return nil, err
		}
	}

	now := time.Now().UTC()
	nowString := fmt.Sprintf("%d-%02d-%02d_%02d-%02d-%02d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second())
	outFile := filepath.Join(outPath, fmt.Sprintf("%s%s", logFile, nowString))

	return os.Create(outFile)
}

// MakeLogger creates a logger that either logs to terminal or to a file. If outputToTerminal
// is true, outputDir will be ignored.
func MakeLogger(outputToTerminal bool, outputDir string) (*log.Logger, *os.File, error) {
	var logger *log.Logger
	if outputToTerminal {
		logger = log.New(os.Stderr, "", log.Flags())
		return logger, nil, nil
	}
	f, err := createLogFile(outputDir)
	if err != nil {
		return nil, nil, err
	}
	logger = log.New(f, "", log.Flags())
	return logger, f, nil
}

// LogFlow is a convenience function for logging common flows..
func LogFlow(logger *log.Logger, f string, status string) {
	logger.Println(strings.Join([]string{"\n##########\n", status, f, "Flow", "\n##########"}, " "))
}

// ReduceServices randomly selects and returns numTestServices from the provided services.
func ReduceServices(logger *log.Logger, allServices []*fpb.Service, numTestServices int) []*fpb.Service {
	reducedServices := make([]*fpb.Service, 0, numTestServices)

	if len(allServices) <= numTestServices {
		reducedServices = allServices
	} else {
		for _, n := range rand.Perm(len(allServices))[0:numTestServices] {
			reducedServices = append(reducedServices, allServices[n])
		}
	}
	logger.Printf("Selected %d services out of a possible %d", len(reducedServices), len(allServices))
	return reducedServices
}

// ParseServiceFeed returns a slice of services for each service in the feed.
func ParseServiceFeed(serviceFeed string) ([]*fpb.Service, error) {
	var feed fpb.ServiceFeed
	content, err := ioutil.ReadFile(serviceFeed)
	if err != nil {
		return nil, fmt.Errorf("unable to read input file: %v", err)
	}
	if path.Ext(serviceFeed) == ".json" {
		if err := jsonpb.UnmarshalString(string(content), &feed); err != nil {
			return nil, fmt.Errorf("unable to parse feed as json: %v", err)
		}
	}
	if path.Ext(serviceFeed) == ".pb3" {
		if err := proto.Unmarshal(content, &feed); err != nil {
			return nil, fmt.Errorf("unable to parse feed as pb3: %v", err)
		}
	}

	if services := feed.GetService(); len(services) != 0 {
		return services, nil
	}
	return nil, errors.New("service feed is empty. At least one service must be present in feed")
}

func merchantService(merchantID, serviceID string) string {
	return strings.Join([]string{merchantID, serviceID}, "||")
}

func buildLineItem(availability *fpb.Availability, tickets []*fpb.TicketType) *mpb.LineItem {
	// If no ticket types return nil as there is nothing to build.
	if len(tickets) == 0 {
		return nil
	}

	// Treated as a set.
	ticketMap := make(map[string]*fpb.TicketType)
	for _, ticketType := range tickets {
		if _, ok := ticketMap[ticketType.GetTicketTypeId()]; !ok {
			// Ticket type ids should be unique to a merchant service pair.
			// If they're not unique they will get dropped silently here.
			// We enforce minimal feed validation in the test client so it's
			// up to you to ensure UIDs.
			ticketMap[ticketType.GetTicketTypeId()] = ticketType
		}
	}

	filteredTickets := tickets
	if len(availability.GetTicketTypeId()) != 0 {
		// Clear slice but preserve allocated memory.
		filteredTickets = filteredTickets[:0]
		for _, ticketTypeID := range availability.GetTicketTypeId() {
			if ticketType, ok := ticketMap[ticketTypeID]; ok {
				filteredTickets = append(filteredTickets, ticketType)
			}
		}
	}

	// If no ticket types return nil as there is nothing to build.
	if len(filteredTickets) == 0 {
		return nil
	}

	lineItem := &mpb.LineItem{
		ServiceId:   availability.GetServiceId(),
		StartSec:    availability.GetStartSec(),
		DurationSec: availability.GetDurationSec(),
		Price:       &mpb.Price{},
	}
	for i := 0; i < int(availability.GetSpotsOpen()); i++ {
		// This is deterministic which is fine given that we just want to get a mix of ticket types.
		ticketTypeIndex := rand.Intn(len(filteredTickets))
		// Calculate price of line item.
		if lineItem.GetPrice().GetCurrencyCode() == "" && filteredTickets[ticketTypeIndex].GetPrice().GetCurrencyCode() != "" {
			lineItem.Price.CurrencyCode = filteredTickets[ticketTypeIndex].GetPrice().GetCurrencyCode()
		}
		lineItem.Price.PriceMicros += filteredTickets[ticketTypeIndex].GetPrice().GetPriceMicros()

		// Add ticket to line item.
		lineItem.Tickets = append(lineItem.Tickets, &mpb.LineItem_OrderedTickets{
			TicketId: filteredTickets[ticketTypeIndex].GetTicketTypeId(),
			Count:    1,
		})
	}

	return lineItem
}

// BuildLineItemMap creats a collection of LineItems from slices of services and availabilities.
func BuildLineItemMap(services []*fpb.Service, availabilities []*fpb.Availability) (map[string][]*mpb.LineItem, error) {
	feedHasTicketType := false
	serviceTicketTypeMap := make(map[string][]*fpb.TicketType)
	for _, service := range services {
		merchantServiceID := merchantService(service.GetMerchantId(), service.GetServiceId())
		for _, ticket := range service.GetTicketType() {
			// TicketType can't have an empty price message or ticket_type_id. If it does it's excluded from map.
			if ticket.GetPrice() == nil || len(ticket.GetTicketTypeId()) == 0 || cmp.Diff(fpb.Price{}, *ticket.GetPrice(), cmp.Comparer(proto.Equal)) == "" {
				continue
			}

			if _, ok := serviceTicketTypeMap[merchantServiceID]; !ok {
				serviceTicketTypeMap[merchantServiceID] = []*fpb.TicketType{}
			}
			feedHasTicketType = true
			serviceTicketTypeMap[merchantServiceID] = append(serviceTicketTypeMap[merchantServiceID], ticket)
		}
	}

	if !feedHasTicketType {
		return nil, errors.New("no valid ticket types found in services, please update services and retry")
	}

	merchantLineItemMap := make(map[string][]*mpb.LineItem)
	for _, availability := range availabilities {
		merchantServiceID := merchantService(availability.GetMerchantId(), availability.GetServiceId())
		if tickets, ok := serviceTicketTypeMap[merchantServiceID]; ok {
			lineItem := buildLineItem(availability, tickets)
			// If lineItem can't be built, don't include in map
			if lineItem == nil {
				continue
			}
			merchantLineItemMap[availability.GetMerchantId()] = append(merchantLineItemMap[availability.GetMerchantId()], lineItem)
		}
	}
	if len(merchantLineItemMap) == 0 {
		return nil, errors.New("no availability slots with ticket type IDs matching those in the service were found")
	}
	return merchantLineItemMap, nil
}

// AvailabilityFrom parses the file specified in availabilityFeed, returning a random permutation of availability data, maximum entries specified in testSlots
func AvailabilityFrom(logger *log.Logger, availabilityFeed string, testSlots int, forRescheduling bool) ([]*fpb.Availability, error) {
	LogFlow(logger, "Parse Input Feed", "Start")
	defer LogFlow(logger, "Parse Input Feed", "End")

	var feed fpb.AvailabilityFeed
	content, err := ioutil.ReadFile(availabilityFeed)
	if err != nil {
		return nil, fmt.Errorf("unable to read input file: %v", err)
	}
	if path.Ext(availabilityFeed) == ".json" {
		if err := jsonpb.UnmarshalString(string(content), &feed); err != nil {
			return nil, fmt.Errorf("unable to parse feed as json: %v", err)
		}
	}
	if path.Ext(availabilityFeed) == ".pb3" {
		if err := proto.Unmarshal(content, &feed); err != nil {
			return nil, fmt.Errorf("unable to parse feed as pb3: %v", err)
		}
	}

	var finalAvailability []*fpb.Availability
	var rawAvailability []*fpb.Availability
	for _, sa := range feed.GetServiceAvailability() {
		rawAvailability = append(rawAvailability, sa.GetAvailability()...)
	}
	if len(rawAvailability) == 0 || testSlots == 0 {
		return finalAvailability, errors.New("no valid availability in feed, exiting workflows")
	}
	if len(rawAvailability) <= testSlots {
		finalAvailability = rawAvailability
	} else {
		nums := rand.Perm(len(rawAvailability))[0:testSlots]
		for _, n := range nums {
			finalAvailability = append(finalAvailability, rawAvailability[n])
			if !forRescheduling {
				continue
			}
			if n > 0 {
				finalAvailability = append(finalAvailability, rawAvailability[n-1])
			}
			if n < testSlots-1 {
				finalAvailability = append(finalAvailability, rawAvailability[n+1])
			}
		}
	}
	logger.Printf("Selected %d slots out of a possible %d", len(finalAvailability), len(rawAvailability))
	return finalAvailability, nil
}

func slotDiff(got, want *mpb.Slot) string {
	// CONFIRMATION_MODE_SYNCHRONOUS and CONFIRMATION_MODE_UNSPECIFIED should be treated as equivalent.
	var gotConfirmationMode, wantConfirmationMode mpb.ConfirmationMode
	var gotComp, wantComp mpb.Slot
	if got != nil {
		gotComp = *got
		gotConfirmationMode = got.GetConfirmationMode()
		gotComp.ConfirmationMode = mpb.ConfirmationMode_CONFIRMATION_MODE_UNSPECIFIED
	}
	if want != nil {
		wantComp = *want
		wantConfirmationMode = want.GetConfirmationMode()
		wantComp.ConfirmationMode = mpb.ConfirmationMode_CONFIRMATION_MODE_UNSPECIFIED
	}
	if diff := cmp.Diff(gotComp, wantComp, cmp.Comparer(proto.Equal)); diff != "" {
		return diff
	}
	if (wantConfirmationMode == mpb.ConfirmationMode_CONFIRMATION_MODE_ASYNCHRONOUS) !=
		(gotConfirmationMode == mpb.ConfirmationMode_CONFIRMATION_MODE_ASYNCHRONOUS) {
		return cmp.Diff(gotConfirmationMode, wantConfirmationMode)
	}
	return ""
}

// ValidateBooking performs granular comparisons between all got and want Bookings.
func ValidateBooking(got, want *mpb.Booking) error {
	if got.GetBookingId() == "" {
		return errors.New("booking_id is empty")
	}
	if diff := slotDiff(got.GetSlot(), want.GetSlot()); diff != "" {
		return fmt.Errorf("slots differ (-got +want)\n%s", diff)
	}
	// UserId is the only required field for the partner to return.
	if diff := cmp.Diff(got.GetUserInformation().GetUserId(), want.GetUserInformation().GetUserId()); diff != "" {
		return fmt.Errorf("users differ (-got +want)\n%s", diff)
	}
	if diff := cmp.Diff(got.GetPaymentInformation(), want.GetPaymentInformation(), cmp.Comparer(proto.Equal)); diff != "" {
		return fmt.Errorf("payment information differs (-got +want)\n%s", diff)
	}
	// 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 want.GetSlot().GetConfirmationMode() == mpb.ConfirmationMode_CONFIRMATION_MODE_ASYNCHRONOUS {
		wantStatus = mpb.BookingStatus_PENDING_MERCHANT_CONFIRMATION
	}
	// If an alternate status is specified, we compare against it instead of the default.
	if want.GetStatus() != mpb.BookingStatus_BOOKING_STATUS_UNSPECIFIED {
		wantStatus = want.GetStatus()
	}
	if diff := cmp.Diff(got.GetStatus(), wantStatus); diff != "" {
		return fmt.Errorf("status differs (-got +want)\n%s", diff)
	}
	return nil
}

// ValidateLineItems performs granular comparisons between got and want LineItem arrays.
func ValidateLineItems(got, want []*mpb.LineItem, confirmStatus bool) error {
	if len(got) != len(want) {
		return fmt.Errorf("number of LineItems differ got %d want %d", len(got), len(want))
	}

	for _, lineItem := range got {
		orderTickets := OrderedTickets(lineItem.GetTickets())
		sort.Sort(orderTickets)
		lineItem.Tickets = orderTickets
	}
	for _, lineItem := range want {
		orderTickets := OrderedTickets(lineItem.GetTickets())
		sort.Sort(orderTickets)
		lineItem.Tickets = orderTickets

		if confirmStatus {
			lineItem.Status = mpb.BookingStatus_CONFIRMED
		}
	}
	sort.Sort(LineItems(got))
	sort.Sort(LineItems(want))

	if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal)); diff != "" {
		return fmt.Errorf("LineItems differ (-got +want)\n%s", diff)
	}

	return nil
}

// ValidateOrder performs granular comparisons between got and want Order messages.
// Params are purposely copied.
func ValidateOrder(got, want mpb.Order) error {
	if got.GetOrderId() == "" {
		return fmt.Errorf("no order id provided for Order %v", got)
	}
	want.OrderId = got.GetOrderId()

	if err := ValidateLineItems(got.GetItem(), want.GetItem(), true); err != nil {
		return err
	}

	// LineItems okay. Remove, free memory, and compare rest of proto.
	want.Item = nil
	got.Item = nil
	if diff := cmp.Diff(got, want, cmp.Comparer(proto.Equal)); diff != "" {
		return fmt.Errorf("order protos differ. LineItems excluded, already validated. (-got +want)\n%s", diff)
	}

	return nil
}

// ValidateOrders performs simple comparisons and set up before forwarding orders
// individually to ValidateOrder.
func ValidateOrders(got, want Orders) error {
	if len(got) != len(want) {
		return fmt.Errorf("number of Orders differ got %d want %d", len(got), len(want))
	}
	sort.Sort(got)
	sort.Sort(want)

	var errorStrings []string
	for i := 0; i < len(got); i++ {
		if err := ValidateOrder(*got[i], *want[i]); err != nil {
			errorStrings = append(errorStrings, err.Error())
		}
	}

	if len(errorStrings) != 0 {
		return errors.New(strings.Join(errorStrings, "\n"))
	}
	return nil
}

func hashLineItemByTicketIds(l *mpb.LineItem) string {
	var uID []string
	for _, ticket := range l.GetTickets() {
		uID = append(uID, ticket.GetTicketId())
	}
	return fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(uID, `|`))))
}

// Orders is a convenience type for an Orders array
type Orders []*mpb.Order

func (o Orders) Len() int {
	return len(o)
}

func (o Orders) Less(i, j int) bool {
	return o[i].GetOrderId() < o[j].GetOrderId()
}

func (o Orders) Swap(i, j int) {
	o[i], o[j] = o[j], o[i]
}

// OrderedTickets is a convenience type for an OrderedTickets array
type OrderedTickets []*mpb.LineItem_OrderedTickets

func (ot OrderedTickets) Len() int {
	return len(ot)
}

func (ot OrderedTickets) Less(i, j int) bool {
	return ot[i].GetTicketId() < ot[j].GetTicketId()
}

func (ot OrderedTickets) Swap(i, j int) {
	ot[i], ot[j] = ot[j], ot[i]
}

// LineItems is a convenience type for a LineItem array
// This sort interface defined below should be used iff
// OrderedTickets have already been sorted AND
// ticket ids are UIDs
type LineItems []*mpb.LineItem

func (l LineItems) Len() int {
	return len(l)
}

func (l LineItems) Less(i, j int) bool {
	return hashLineItemByTicketIds(l[i]) < hashLineItemByTicketIds(l[j])
}

func (l LineItems) Swap(i, j int) {
	l[i], l[j] = l[j], l[i]
}

// BuildSlotFrom creates a bookingservice slot from an feed availability record.
func BuildSlotFrom(a *fpb.Availability) (*mpb.Slot, error) {
	r := a.GetResources()
	confirmationMode := mpb.ConfirmationMode_CONFIRMATION_MODE_UNSPECIFIED
	if a.GetConfirmationMode() == fpb.Availability_CONFIRMATION_MODE_SYNCHRONOUS {
		confirmationMode = mpb.ConfirmationMode_CONFIRMATION_MODE_SYNCHRONOUS
	} else if a.GetConfirmationMode() == fpb.Availability_CONFIRMATION_MODE_ASYNCHRONOUS {
		confirmationMode = mpb.ConfirmationMode_CONFIRMATION_MODE_ASYNCHRONOUS
	}
	return &mpb.Slot{
		MerchantId:       a.GetMerchantId(),
		ServiceId:        a.GetServiceId(),
		StartSec:         a.GetStartSec(),
		DurationSec:      a.GetDurationSec(),
		AvailabilityTag:  a.GetAvailabilityTag(),
		ConfirmationMode: confirmationMode,
		Resources: &mpb.ResourceIds{
			StaffId:   r.GetStaffId(),
			RoomId:    r.GetRoomId(),
			PartySize: r.GetPartySize(),
		},
	}, nil
}

// SplitAvailabilityByMerchant splits the list of availabilities by merchant. This is necessary if BatchAvailabilityLookup
// is enabled, since each BAL request handles one merchant.
func SplitAvailabilityByMerchant(av []*fpb.Availability) map[string][]*fpb.Availability {
	ret := make(map[string][]*fpb.Availability)
	for _, a := range av {
		ret[a.GetMerchantId()] = append(ret[a.GetMerchantId()], a)
	}
	return ret
}

// BuildBatchAvailabilityLookupRequestFrom creates a BatchAvailabilityLookupRequest from a list of input availability slots.
func BuildBatchAvailabilityLookupRequestFrom(av []*fpb.Availability) (*mpb.BatchAvailabilityLookupRequest, error) {
	var st []*mpb.SlotTime
	var m string
	var s string
	for _, a := range av {
		if m == "" {
			m = a.GetMerchantId()
			s = a.GetServiceId()
		} else if m != a.GetMerchantId() {
			return nil, fmt.Errorf("BuildBatchAvailabilityLookupRequestFrom failed, got multiple merchant ids: %s, %s", m, a.GetMerchantId())
		}
		r := a.GetResources()
		st = append(st, &mpb.SlotTime{
			ServiceId:       s,
			StartSec:        a.GetStartSec(),
			DurationSec:     a.GetDurationSec(),
			AvailabilityTag: a.GetAvailabilityTag(),
			ResourceIds: &mpb.ResourceIds{
				StaffId:   r.GetStaffId(),
				RoomId:    r.GetRoomId(),
				PartySize: r.GetPartySize(),
			},
		})
	}
	return &mpb.BatchAvailabilityLookupRequest{
		MerchantId: m,
		SlotTime:   st,
	}, nil
}

// BuildMerchantServiceMap creates a key value pair of unique services to all of their availability slots.
func BuildMerchantServiceMap(av []*fpb.Availability) map[SlotKey][]*fpb.Availability {
	m := make(map[SlotKey][]*fpb.Availability)
	for _, a := range av {
		key := SlotKey{
			MerchantID: a.GetMerchantId(),
			ServiceID:  a.GetServiceId(),
			StaffID:    a.GetResources().GetStaffId(),
			RoomID:     a.GetResources().GetRoomId(),
		}
		m[key] = append(m[key], a)
	}
	return m
}

// ValidateWaitEstimate validates all the fields are populated for the wait estimate.
func ValidateWaitEstimate(waitEstimate *wpb.WaitEstimate) error {
	if waitEstimate.GetPartySize() <= 0 {
		return errors.New("party size <= 0")
	}
	waitLength := waitEstimate.GetWaitLength()
	if waitLength == nil {
		return errors.New("wait length not specified")
	}
	if waitLength.GetPartiesAheadCount() < 0 {
		return errors.New("parties ahead count < 0")
	}
	estimatedSeatTimeRange := waitLength.GetEstimatedSeatTimeRange()
	if estimatedSeatTimeRange == nil {
		return nil
	}
	if estimatedSeatTimeRange.GetStartSeconds() <= 0 {
		return errors.New("estimated seat time range provided and start seconds <= 0")
	}
	if estimatedSeatTimeRange.GetEndSeconds() <= 0 {
		return errors.New("estimated seat time range provided and end seconds <= 0")
	}
	return nil
}

// ValidateWaitlistEntry validates all the fields are populated for the waitlist entry.
func ValidateWaitlistEntry(waitlistEntry *wpb.WaitlistEntry) error {
	if waitlistEntry.GetWaitlistEntryState() == wpb.WaitlistEntryState_WAITLIST_ENTRY_STATE_UNSPECIFIED {
		return errors.New("waitlist entry state not specified")
	}
	stateTimes := waitlistEntry.GetWaitlistEntryStateTimes()
	if stateTimes == nil {
		return errors.New("WaitlistEntryStateTimes not specified")
	}
	if stateTimes.GetCreatedTimeSeconds() <= 0 {
		return errors.New("created time seconds <= 0")
	}
	waitEstimate := waitlistEntry.GetWaitEstimate()
	if waitEstimate == nil {
		return errors.New("wait estimate not specified")
	}
	return ValidateWaitEstimate(waitEstimate)
}
