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

import (
	"crypto/md5"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"path"
	"sort"
	"strings"

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

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

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

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 {
	lineItem := &mpb.LineItem{
		ServiceId:   availability.GetServiceId(),
		StartSec:    availability.GetStartSec(),
		DurationSec: availability.GetDurationSec(),
		Price:       &mpb.Price{},
	}

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

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

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

	return lineItem
}

// MerchantLineItemMapFrom attempts to build a collection of LineItems from a service and availability feed.
func MerchantLineItemMapFrom(serviceFeed, availabilityFeed string, testSlots int) (map[string][]*mpb.LineItem, error) {
	services, err := parseServiceFeed(serviceFeed)
	if err != nil {
		return nil, err
	}

	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.
			diff := cmp.Diff(&fpb.Price{}, ticket.GetPrice(), cmp.Comparer(proto.Equal))
			if len(ticket.GetTicketTypeId()) == 0 || diff == "" {
				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 service feed, please update service feed and retry")
	}

	availabilities, err := AvailabilityFrom(availabilityFeed, testSlots)
	if err != nil {
		return nil, err
	}

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

	return merchantLineItemMap, nil
}

// AvailabilityFrom parses the file specified in availabilityFeed, returning a random permutation of availability data, maximum entries specified in testSlots
func AvailabilityFrom(availabilityFeed string, testSlots int) ([]*fpb.Availability, error) {
	LogFlow("Parse Input Feed", "Start")
	defer LogFlow("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])
		}
	}
	log.Printf("Selected %d slots out of a possible %d", len(finalAvailability), len(rawAvailability))
	return finalAvailability, nil
}

// 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 := cmp.Diff(got.GetSlot(), want.GetSlot(), cmp.Comparer(proto.Equal)); 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 want overrides it.
	wantStatus := mpb.BookingStatus_CONFIRMED
	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", md5.Sum([]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()
	return &mpb.Slot{
		MerchantId:      a.GetMerchantId(),
		ServiceId:       a.GetServiceId(),
		StartSec:        a.GetStartSec(),
		DurationSec:     a.GetDurationSec(),
		AvailabilityTag: a.GetAvailabilityTag(),
		Resources: &mpb.ResourceIds{
			StaffId:   r.GetStaffId(),
			RoomId:    r.GetRoomId(),
			PartySize: r.GetPartySize(),
		},
	}, 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
}
