/*
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 waitlist contains test logic for waitlist related endpoints.
package waitlist

import (
	"context"
	"log"

	fpb "github.com/maps-booking-v3/feeds"
	"github.com/maps-booking-v3/api"
	"github.com/maps-booking-v3/utils"
)

func logStats(stats *utils.TestSummary, logger *log.Logger, config *utils.Config) {
	logger.Println("\n************* Begin Stats *************\n")
	var totalErrors int
	if config.WaitlistHealthFlow || config.WaitlistAllFlows {
		if stats.WaitlistHealthCheckSuccess {
			logger.Println("HealthCheck Succeeded")
		} else {
			totalErrors++
			logger.Println("HealthCheck Failed")
		}
	}
	if config.WaitlistBatchGetWaitEstimatesFlow || config.WaitlistAllFlows {
		totalErrors += stats.WaitlistBatchGetWaitEstimatesErrors
		logger.Printf("BatchGetWaitEstimates Errors: %d/%d", stats.WaitlistBatchGetWaitEstimatesErrors, stats.WaitlistBatchGetWaitEstimatesErrors+stats.WaitlistBatchGetWaitEstimatesSuccess)
	}
	if config.WaitlistCreateWaitlistEntryFlow || config.WaitlistAllFlows {
		totalErrors += stats.WaitlistCreateWaitlistEntryErrors
		logger.Printf("CreateWaitlistEntry Errors: %d/%d", stats.WaitlistCreateWaitlistEntryErrors, stats.WaitlistCreateWaitlistEntryErrors+stats.WaitlistCreateWaitlistEntrySuccess)
	}
	if config.WaitlistGetWaitlistEntryFlow || config.WaitlistAllFlows {
		totalErrors += stats.WaitlistGetWaitlistEntryErrors
		logger.Printf("GetWaitlistEntry Errors: %d/%d", stats.WaitlistGetWaitlistEntryErrors, stats.WaitlistGetWaitlistEntryErrors+stats.WaitlistGetWaitlistEntrySuccess)
	}
	if config.WaitlistDeleteWaitlistEntryFlow || config.WaitlistAllFlows {
		totalErrors += stats.WaitlistDeleteWaitlistEntryErrors
		logger.Printf("DeleteWaitlistEntry Errors: %d/%d", stats.WaitlistDeleteWaitlistEntryErrors, stats.WaitlistDeleteWaitlistEntryErrors+stats.WaitlistDeleteWaitlistEntrySuccess)
	}

	logger.Println("\n\n\n")
	if totalErrors == 0 {
		logger.Println("All Tests Pass!")
	} else {
		logger.Printf("Found %d Errors", totalErrors)
	}

	logger.Println("\n************* End Stats *************\n")
}

// generateWaitlistEntries creates a waitlist entry for each provided service.
func generateWaitlistEntries(ctx context.Context, logger *log.Logger, services []*fpb.Service, stats *utils.TestSummary, conn *utils.HTTPConnection) []string {
	logger.Println("no previous waitlist entries to use, acquiring new inventory")
	utils.LogFlow(logger, "Generate Fresh Entries", "Start")
	defer utils.LogFlow(logger, "Generate Fresh Entries", "End")

	var out []string
	totalServices := len(services)
	for i, s := range services {
		id, err := api.CreateWaitlistEntry(ctx, logger, s, conn)
		if err != nil {
			logger.Printf("%s. skipping waitlistEntry %d/%d, serviceID: %s",
				err.Error(), i, totalServices, s.GetServiceId())
			stats.WaitlistCreateWaitlistEntryErrors++
			continue
		}
		out = append(out, id)
		stats.WaitlistCreateWaitlistEntrySuccess++
	}
	return out
}

// RunTests runs waitlist tests.
func RunTests(ctx context.Context, logger *log.Logger, config *utils.Config, reducedServices []*fpb.Service, stats *utils.TestSummary) {
	// HealthCheck Flow
	conn := config.Conn
	if config.WaitlistHealthFlow || config.WaitlistAllFlows {
		stats.WaitlistHealthCheckSuccess = true
		if err := api.HealthCheck(ctx, logger, conn); err != nil {
			stats.WaitlistHealthCheckSuccess = false
			logger.Println(err.Error())
		}
		stats.WaitlistHealthCheckCompleted = true
		if !config.WaitlistAllFlows && !config.WaitlistBatchGetWaitEstimatesFlow && !config.WaitlistCreateWaitlistEntryFlow &&
			!config.WaitlistGetWaitlistEntryFlow && !config.WaitlistDeleteWaitlistEntryFlow {
			logStats(stats, logger, config)
			return
		}
	}

	// BatchGetWaitEstimates Flow
	if config.WaitlistBatchGetWaitEstimatesFlow || config.WaitlistAllFlows {
		utils.LogFlow(logger, "BatchGetWaitEstimates", "Start")

		for i, s := range reducedServices {
			if err := api.BatchGetWaitEstimates(ctx, logger, s, conn); err != nil {
				logger.Printf("%s. BatchGerWaitEstimates failed for service %d/%d. Service_id: %s",
					err.Error(), i, stats.WaitlistTotalServicesProcessed, s.GetServiceId())
				stats.WaitlistBatchGetWaitEstimatesErrors++
				continue
			}
			stats.WaitlistBatchGetWaitEstimatesSuccess++
		}
		stats.WaitlistBatchGetWaitEstimatesCompleted = true
		utils.LogFlow(logger, "BatchGetWaitEstimates", "End")
	}
	// CreateWaitlistEntry Flow.
	var ids []string
	if config.WaitlistCreateWaitlistEntryFlow || config.WaitlistGetWaitlistEntryFlow ||
		config.WaitlistDeleteWaitlistEntryFlow || config.WaitlistAllFlows {
		utils.LogFlow(logger, "CreateWaitlistEntry", "Start")
		ids = generateWaitlistEntries(ctx, logger, reducedServices, stats, conn)
		stats.WaitlistCreateWaitlistEntryCompleted = true
		utils.LogFlow(logger, "CreateWaitlistEntry", "End")
	}
	// GetWaitlistEntry Flow
	if config.WaitlistGetWaitlistEntryFlow || config.WaitlistAllFlows {
		utils.LogFlow(logger, "GetWaitlistEntry", "Start")
		for _, id := range ids {
			if _, err := api.GetWaitlistEntry(ctx, logger, id, conn); err != nil {
				logger.Printf("%s. get waitlist entry failed for waitlist entry id: %s",
					err.Error(), id)
				stats.WaitlistGetWaitlistEntryErrors++
				continue
			}
			stats.WaitlistGetWaitlistEntrySuccess++
		}
		stats.WaitlistGetWaitlistEntryCompleted = true
		utils.LogFlow(logger, "GetWaitlistEntry", "End")
	}

	// DeleteWaitlistentry Flow
	if config.WaitlistDeleteWaitlistEntryFlow || config.WaitlistAllFlows {
		utils.LogFlow(logger, "DeleteWaitlistEntry", "Start")

		for _, id := range ids {
			if err := api.DeleteWaitlistEntry(ctx, logger, id, conn); err != nil {
				logger.Printf("%s. Delete waitlist entry failed for waitlist entry id: %s",
					err.Error(), id)
				stats.WaitlistDeleteWaitlistEntryErrors++
				continue
			}
			stats.WaitlistDeleteWaitlistEntrySuccess++
		}
		stats.WaitlistDeleteWaitlistEntryCompleted = true
		utils.LogFlow(logger, "DeleteWaitlistEntry", "End")
	}
	logStats(stats, logger, config)
}
