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

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"

	"github.com/maps-booking-v3/api"
	"github.com/maps-booking-v3/utils"

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

const logFile = "http_test_client_log_"

var (
	serverAddr                = flag.String("server_addr", "example.com:80", "Your http server's address in the format of host:port")
	credentialsFile           = flag.String("credentials_file", "", "File containing credentials for your server. Leave blank to bypass authentication. File should have exactly one line of the form 'username:password'.")
	numTestServices           = flag.Int("num_test_services", 10, "Maximum number of services to test from service_feed. Services will be selected randomly")
	allFlows                  = flag.Bool("all_tests", false, "Whether to test all endpoints.")
	healthFlow                = flag.Bool("health_check_test", false, "Whether to test the Health endpoint.")
	batchGetWaitEstimatesFlow = flag.Bool("batch_get_wait_estimates_test", false, "Whether to test the BatchGetWaitEstimates endpoint.")
	createWaitlistEntryFlow   = flag.Bool("create_waitlist_entry_test", false, "Whether to test the CreateWaitlistEntry endpoint.")
	getWaitlistEntryFlow      = flag.Bool("get_waitlist_entry_test", false, "Whether to test the GetWaitlistEntry endpoint. CreateWaitlistEntry will also be called to create the entries.")
	deleteWaitlistEntryFlow   = flag.Bool("delete_waitlist_entry_test", false, "Whether to test the DeleteWaitlistEntry endpoint. CreateWaitlistEntry will also be called to create the entries.")
	serviceFeed               = flag.String("service_feed", "", "Absolute path to service feed required for all tests except health. Feeds can be in either json or pb3 format.")
	outputDir                 = flag.String("output_dir", "", "Absolute path of dir to dump log file.")
	caFile                    = flag.String("ca_file", "", "Absolute path to your server's Certificate Authority root cert. Downloading all roots currently recommended by the Google Internet Authority is a suitable alternative https://pki.google.com/roots.pem. Leave blank to connect using http rather than https.")
	fullServerName            = flag.String("full_server_name", "", "Fully qualified domain name. Same name used to sign CN. Only necessary if ca_file is specified and the base URL differs from the server address.")
	outputToTerminal          = flag.Bool("output_to_terminal", false, "Output to terminal rather than a file.")
)

type counters struct {
	TotalServicesProcessed       int
	HealthCheckSuccess           bool
	BatchGetWaitEstimatesSuccess int
	BatchGetWaitEstimatesErrors  int
	CreateWaitlistEntrySuccess   int
	CreateWaitlistEntryErrors    int
	GetWaitlistEntrySuccess      int
	GetWaitlistEntryErrors       int
	DeleteWaitlistEntrySuccess   int
	DeleteWaitlistEntryErrors    int
}

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

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

func createLogFile() (*os.File, error) {
	var err error
	outPath := *outputDir
	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)
}

func logStats(stats counters) {
	log.Println("\n************* Begin Stats *************\n")
	var totalErrors int
	if *healthFlow || *allFlows {
		if stats.HealthCheckSuccess {
			log.Println("HealthCheck Succeeded")
		} else {
			totalErrors++
			log.Println("HealthCheck Failed")
		}
	}
	if *batchGetWaitEstimatesFlow || *allFlows {
		totalErrors += stats.BatchGetWaitEstimatesErrors
		log.Printf("BatchGetWaitEstimates Errors: %d/%d", stats.BatchGetWaitEstimatesErrors, stats.BatchGetWaitEstimatesErrors+stats.BatchGetWaitEstimatesSuccess)
	}
	if *createWaitlistEntryFlow || *allFlows {
		totalErrors += stats.CreateWaitlistEntryErrors
		log.Printf("CreateWaitlistEntry Errors: %d/%d", stats.CreateWaitlistEntryErrors, stats.CreateWaitlistEntryErrors+stats.CreateWaitlistEntrySuccess)
	}
	if *getWaitlistEntryFlow || *allFlows {
		totalErrors += stats.GetWaitlistEntryErrors
		log.Printf("GetWaitlistEntry Errors: %d/%d", stats.GetWaitlistEntryErrors, stats.GetWaitlistEntryErrors+stats.GetWaitlistEntrySuccess)
	}
	if *deleteWaitlistEntryFlow || *allFlows {
		totalErrors += stats.DeleteWaitlistEntryErrors
		log.Printf("DeleteWaitlistEntry Errors: %d/%d", stats.DeleteWaitlistEntryErrors, stats.DeleteWaitlistEntryErrors+stats.DeleteWaitlistEntrySuccess)
	}

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

	log.Println("\n************* End Stats *************\n")
	os.Exit(totalErrors)
}

func main() {
	flag.Parse()
	var stats counters

	if !*outputToTerminal {
		// Set up logging before continuing with flows
		f, err := createLogFile()
		if err != nil {
			log.Fatalf("Failed to create log file %v", err)
		}
		defer f.Close()
		log.SetOutput(f)
	}

	conn, err := api.InitHTTPConnection(*serverAddr, *credentialsFile, *caFile, *fullServerName)
	if err != nil {
		log.Fatalf("Failed to init http connection %v", err)
	}

	// HealthCheck Flow
	if *healthFlow || *allFlows {
		stats.HealthCheckSuccess = true
		if err := api.HealthCheck(conn); err != nil {
			stats.HealthCheckSuccess = false
			log.Println(err.Error())
		}
		if !*allFlows && !*batchGetWaitEstimatesFlow && !*createWaitlistEntryFlow &&
			!*getWaitlistEntryFlow && !*deleteWaitlistEntryFlow {
			logStats(stats)
		}
	}

	// Build services.
	if *serviceFeed == "" {
		log.Fatal("please set service_feed flag if you wish to test additional flows")
	}

	var services []*fpb.Service
	services, err = utils.ParseServiceFeed(*serviceFeed)
	if err != nil {
		log.Fatalf("Failed to get services: %v", err.Error())
	}
	// Remove services without waitlist rules.
	waitlistServices := services[:0]
	for _, s := range services {
		if s.GetWaitlistRules() != nil {
			waitlistServices = append(waitlistServices, s)
		}
	}

	if len(waitlistServices) == 0 {
		log.Fatal("no services have waitlist rules")
	}
	reducedServices := utils.ReduceServices(waitlistServices, *numTestServices)
	stats.TotalServicesProcessed += len(reducedServices)

	// BatchGetWaitEstimates Flow
	if *batchGetWaitEstimatesFlow || *allFlows {
		utils.LogFlow("BatchGetWaitEstimates", "Start")

		for i, s := range reducedServices {
			if err = api.BatchGetWaitEstimates(s, conn); err != nil {
				log.Printf("%s. BatchGerWaitEstimates failed for service %d/%d. Service_id:",
					err.Error(), i, stats.TotalServicesProcessed, s.GetServiceId())
				stats.BatchGetWaitEstimatesErrors++
				continue
			}
			stats.BatchGetWaitEstimatesSuccess++
		}
		utils.LogFlow("BatchGetWaitEstimates", "End")
	}
	// CreateWaitlistEntry Flow.
	var ids []string
	if *createWaitlistEntryFlow || *getWaitlistEntryFlow ||
		*deleteWaitlistEntryFlow || *allFlows {
		utils.LogFlow("CreateWaitlistEntry", "Start")
		ids = GenerateWaitlistEntries(reducedServices, &stats, conn)
		utils.LogFlow("CreateWaitlistEntry", "End")
	}
	// GetWaitlistEntry Flow
	if *getWaitlistEntryFlow || *allFlows {
		utils.LogFlow("GetWaitlistEntry", "Start")
		for _, id := range ids {
			if _, err = api.GetWaitlistEntry(id, conn); err != nil {
				log.Printf("%s. get waitlist entry failed for waitlist entry id: %s",
					err.Error(), id)
				stats.GetWaitlistEntryErrors++
				continue
			}
			stats.GetWaitlistEntrySuccess++
		}
		utils.LogFlow("GetWaitlistEntry", "End")
	}

	// DeleteWaitlistentry Flow
	if *deleteWaitlistEntryFlow || *allFlows {
		utils.LogFlow("DeleteWaitlistEntry", "Start")

		for _, id := range ids {
			if err = api.DeleteWaitlistEntry(id, conn); err != nil {
				log.Printf("%s. Delete waitlist entry failed for waitlist entry id: %s",
					err.Error(), id)
				stats.DeleteWaitlistEntryErrors++
				continue
			}
			stats.DeleteWaitlistEntrySuccess++
		}
		utils.LogFlow("DeleteWaitlistEntry", "End")
	}

	logStats(stats)
}
