package test

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// DEPRECATED_GROUPS stores API groups that are deprecated and therefore are not supported in further developement
var DEPRECATED_GROUPS = []string{
	"/cloudapi/machine/",
	"/cloudapi/cloudspace/",
	"//cloudbroker/pgpu/",
	"/cloudapi/gpu/",
	"/cloudapi/portforwarding/",
	"/cloudapi/account/create",
	"/cloudapi/account/listVMs",
	"/cloudapi/account/listCS",
	"/cloudapi/account/getStats",
	"/cloudapi/vgpu/list",
	"/cloudapi/compute/affinityGroupCheckStart",
	"/cloudapi/vins/staticRouteAccessGrant",
	"/cloudapi/vins/staticRouteAccessRevoke",
	"/cloudbroker/resource_optimizer",

	"/cloudbroker/account/listVMs",
	"/cloudbroker/account/listCS",
	"/cloudbroker/machine/",
	"/cloudbroker/bservice/",
	"/cloudbroker/auditcollector/",
	"/cloudbroker/health/",
	"/cloudbroker/metering/",
	"/cloudbroker/cloudspace/",
	"/cloudbroker/vnfdev/",
	"/cloudbroker/auditbeat/",
	"/cloudbroker/zeroaccess/",
	"/cloudbroker/qos/",
	"/cloudbroker/backupcreator/",
	"/cloudbroker/resmon/",
	"/cloudbroker/pgpu/",
	"/cloudbroker/job/",
	"/cloudbroker/tlock/",
	"/cloudbroker/eco/",
	"/cloudbroker/iaas/",
	"/cloudbroker/diagnostics/",
	"/cloudbroker/milestones/",
	"/cloudbroker/compute/affinityGroupCheckStart",
	"/cloudbroker/vins/staticRouteAccessGrant",
	"/cloudbroker/vins/staticRouteAccessRevoke",
	"/restmachine/cloudbroker/image/updateNodes",
	"/restmachine/cloudbroker/image/uploadImageFile",
}

// getUrlsFromBytes converts bytes to array of urls strings
func getUrlsFromBytes(bytes []byte) ([]string, error) {
	paths, err := getMapFromFile(bytes)
	if err != nil {
		return nil, err
	}

	urls := make([]string, 0, len(paths))
	for p := range paths {
		if validateUrlFromJson(p) {
			urls = append(urls, p)
		}
	}

	return urls, nil
}

func validateUrlFromJson(url string) bool {
	if !strings.HasPrefix(url, "/restmachine/cloudapi/") && !strings.HasPrefix(url, "/restmachine/cloudbroker/") && !strings.HasPrefix(url, "/restmachine/sdn/") {
		return false
	}

	for _, deprecated := range DEPRECATED_GROUPS {
		if strings.Contains(url, deprecated) {
			return false
		}
	}

	return true
}

// getMissingDecortUrls returns array of url strings that are present in json swagger docs and absent in decort-sdk handlers.
func getMissingDecortUrls(jsonUrls, decortUrls []string) []string {
	result := make([]string, 0, len(jsonUrls))
	for _, jsonUrl := range jsonUrls {
		var found bool
		for _, decortUrl := range decortUrls {
			if jsonUrl == decortUrl {
				found = true
				break
			}
		}

		if !found {
			result = append(result, jsonUrl)
		}
	}

	return result
}

// getMissingDecortUrls returns array of url strings that are present in json swagger docs and absent in decort-sdk handlers.
func getDeprecatedDecortUrls(jsonUrls, decortUrls []string) []string {
	result := make([]string, 0, len(decortUrls))
	for _, decortUrl := range decortUrls {
		var found bool
		for _, jsonUrl := range jsonUrls {
			if jsonUrl == decortUrl {
				found = true
				break
			}
		}

		if !found && validateUrlFromJson(decortUrl) {
			result = append(result, decortUrl)
		}
	}

	return result
}

// readUrlFromDir reads all url addresses from given directory and its subdirectories and subfiles and returns array of urls found. Capacity will
func readUrlFromDir(dirName string, capacity int) []string {
	result := make([]string, 0, capacity)

	items, _ := os.ReadDir(dirName)

	for _, item := range items {
		itemName := dirName + "/" + item.Name()
		if item.IsDir() {
			subitems, _ := os.ReadDir(itemName)

			for _, subitem := range subitems {
				subName := itemName + "/" + subitem.Name()
				files, _ := os.ReadDir(subName)
				if item.IsDir() {
					for _, file := range files {
						fileName := dirName + "/" + item.Name() + "/" + subitem.Name() + "/" + file.Name()
						if !file.IsDir() {
							url, err := readUrlFromFile(fileName)
							if err != nil {
								continue
							}
							result = append(result, url...)
						}
					}
				}

				if !subitem.IsDir() {
					url, err := readUrlFromFile(subName)
					if err != nil {
						continue
					}
					result = append(result, url...)
				}
			}

		} else {
			url, err := readUrlFromFile(itemName)
			if err != nil {
				continue
			}
			result = append(result, url...)

		}
	}
	return result
}

// readUrlFromFile reads url address of format 	url := "/cloudapi/vins/audits" or 	url := "/cloudbroker/vins/audits" from file with name fileName.
func readUrlFromFile(fileName string) ([]string, error) {
	var result []string
	file, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), `"/cloudapi/`) {
			indexStart := strings.Index(scanner.Text(), "/cloudapi/")
			url := strings.Trim(scanner.Text()[indexStart:], `"`)
			result = append(result, "/restmachine"+url)
		}
		if strings.Contains(scanner.Text(), `"/cloudbroker/`) {
			indexStart := strings.Index(scanner.Text(), "/cloudbroker/")
			url := strings.Trim(scanner.Text()[indexStart:], `"`)
			result = append(result, "/restmachine"+url)
		}
		if strings.Contains(scanner.Text(), `"/sdn/`) {
			indexStart := strings.Index(scanner.Text(), "/sdn/")
			url := strings.Trim(scanner.Text()[indexStart:], `"`)
			result = append(result, "/restmachine"+url)
		}
	}

	if len(result) == 0 {
		return nil, fmt.Errorf("file %s doesn't contain any url", fileName)
	}
	return result, nil
}
