package redfishprofile

import (
	"regexp"
	"strings"
)

var (
	outboardCardHintRe = regexp.MustCompile(`/outboardPCIeCard\d+(?:/|$)`)
	obDriveHintRe      = regexp.MustCompile(`/Drives/OB\d+$`)
	fpDriveHintRe      = regexp.MustCompile(`/Drives/FP00HDD\d+$`)
	vrFirmwareHintRe   = regexp.MustCompile(`^CPU\d+_PVCC.*_VR$`)
)

var inspurGroupOEMFirmwareHints = map[string]struct{}{
	"Front_HDD_CPLD0": {},
	"MainBoard0CPLD":  {},
	"MainBoardCPLD":   {},
	"PDBBoardCPLD":    {},
	"SCMCPLD":         {},
	"SWBoardCPLD":     {},
}

func inspurGroupOEMPlatformsProfile() Profile {
	return staticProfile{
		name:            "inspur-group-oem-platforms",
		priority:        25,
		safeForFallback: false,
		matchFn: func(s MatchSignals) int {
			topologyScore := 0
			boardScore := 0
			chassisOutboard := matchedPathTokens(s.ResourceHints, "/redfish/v1/Chassis/", outboardCardHintRe)
			systemOutboard := matchedPathTokens(s.ResourceHints, "/redfish/v1/Systems/", outboardCardHintRe)
			obDrives := matchedPathTokens(s.ResourceHints, "", obDriveHintRe)
			fpDrives := matchedPathTokens(s.ResourceHints, "", fpDriveHintRe)
			firmwareNames, vrFirmwareNames := inspurGroupOEMFirmwareMatches(s.ResourceHints)

			if len(chassisOutboard) > 0 {
				topologyScore += 20
			}
			if len(systemOutboard) > 0 {
				topologyScore += 10
			}
			switch {
			case len(obDrives) > 0 && len(fpDrives) > 0:
				topologyScore += 15
			}
			switch {
			case len(firmwareNames) >= 2:
				boardScore += 15
			}
			switch {
			case len(vrFirmwareNames) >= 2:
				boardScore += 10
			}
			if anySignalContains(s, "COMMONbAssembly") {
				boardScore += 12
			}
			if anySignalContains(s, "EnvironmentMetrcs") {
				boardScore += 8
			}
			if anySignalContains(s, "GetServerAllUSBStatus") {
				boardScore += 8
			}
			if topologyScore == 0 || boardScore == 0 {
				return 0
			}
			return min(topologyScore+boardScore, 100)
		},
		extendAcquisition: func(plan *AcquisitionPlan, _ MatchSignals) {
			addPlanNote(plan, "Inspur Group OEM platform fingerprint matched")
		},
		applyAnalysisDirectives: func(d *AnalysisDirectives, _ MatchSignals) {
			d.EnableGenericGraphicsControllerDedup = true
		},
	}
}

func matchedPathTokens(paths []string, requiredPrefix string, re *regexp.Regexp) []string {
	seen := make(map[string]struct{})
	for _, rawPath := range paths {
		path := normalizePath(rawPath)
		if path == "" || (requiredPrefix != "" && !strings.HasPrefix(path, requiredPrefix)) {
			continue
		}
		token := re.FindString(path)
		if token == "" {
			continue
		}
		token = strings.Trim(token, "/")
		if token == "" {
			continue
		}
		seen[token] = struct{}{}
	}
	out := make([]string, 0, len(seen))
	for token := range seen {
		out = append(out, token)
	}
	return dedupeSorted(out)
}

func inspurGroupOEMFirmwareMatches(paths []string) ([]string, []string) {
	firmwareNames := make(map[string]struct{})
	vrNames := make(map[string]struct{})
	for _, rawPath := range paths {
		path := normalizePath(rawPath)
		if !strings.HasPrefix(path, "/redfish/v1/UpdateService/FirmwareInventory/") {
			continue
		}
		name := strings.TrimSpace(path[strings.LastIndex(path, "/")+1:])
		if name == "" {
			continue
		}
		if _, ok := inspurGroupOEMFirmwareHints[name]; ok {
			firmwareNames[name] = struct{}{}
		}
		if vrFirmwareHintRe.MatchString(name) {
			vrNames[name] = struct{}{}
		}
	}
	return mapKeysSorted(firmwareNames), mapKeysSorted(vrNames)
}

func anySignalContains(signals MatchSignals, needle string) bool {
	needle = strings.TrimSpace(needle)
	if needle == "" {
		return false
	}
	for _, signal := range signals.ResourceHints {
		if strings.Contains(signal, needle) {
			return true
		}
	}
	for _, signal := range signals.DocHints {
		if strings.Contains(signal, needle) {
			return true
		}
	}
	return false
}

func mapKeysSorted(items map[string]struct{}) []string {
	out := make([]string, 0, len(items))
	for item := range items {
		out = append(out, item)
	}
	return dedupeSorted(out)
}
