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

// AvailabilityToSlotTime converts an Availability object to SlotTime.
func AvailabilityToSlotTime(a *fpb.Availability) *mpb.SlotTime {
	slot := &mpb.SlotTime{
		ServiceId:       a.GetServiceId(),
		StartSec:        a.GetStartSec(),
		DurationSec:     a.GetDurationSec(),
		AvailabilityTag: a.GetAvailabilityTag()}
	if a.Resources != nil {
		r := a.GetResources()
		slot.ResourceIds = &mpb.ResourceIds{
			StaffId:   r.GetStaffId(),
			RoomId:    r.GetRoomId(),
			PartySize: r.GetPartySize(),
		}
	}
	return slot
}

// 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) {
	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
	}
	slot := &mpb.Slot{
		MerchantId:       a.GetMerchantId(),
		ServiceId:        a.GetServiceId(),
		StartSec:         a.GetStartSec(),
		DurationSec:      a.GetDurationSec(),
		AvailabilityTag:  a.GetAvailabilityTag(),
		ConfirmationMode: confirmationMode,
	}
	if a.Resources != nil {
		r := a.GetResources()
		slot.Resources = &mpb.ResourceIds{
			StaffId:   r.GetStaffId(),
			RoomId:    r.GetRoomId(),
			PartySize: r.GetPartySize(),
		}
	}
	return slot, 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
	for _, a := range av {
		if m == "" {
			m = a.GetMerchantId()
		} else if m != a.GetMerchantId() {
			return nil, fmt.Errorf("BuildBatchAvailabilityLookupRequestFrom failed, got multiple merchant ids: %s, %s", m, a.GetMerchantId())
		}
		st = append(st, AvailabilityToSlotTime(a))
	}
	return &mpb.BatchAvailabilityLookupRequest{
		MerchantId: m,
		SlotTime:   st,
	}, nil
}

// BuildBatchAvailabilityLookupResponseFrom creates a BatchAvailabilityLookupResponse from a list of input availability slots.
func BuildBatchAvailabilityLookupResponseFrom(av []*fpb.Availability) (*mpb.BatchAvailabilityLookupResponse, error) {
	var sta []*mpb.SlotTimeAvailability
	var m string
	for _, a := range av {
		if m == "" {
			m = a.GetMerchantId()
		} else if m != a.GetMerchantId() {
			return nil, fmt.Errorf("BuildBatchAvailabilityLookupRequestFrom failed, got multiple merchant ids: %s, %s", m, a.GetMerchantId())
		}
		sta = append(sta, &mpb.SlotTimeAvailability{
			Available: a.SpotsOpen > 0,
			SlotTime:  AvailabilityToSlotTime(a),
		})
	}
	return &mpb.BatchAvailabilityLookupResponse{
		SlotTimeAvailability: sta,
	}, 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)
}
