package sonar

import (
	"strconv"
	"strings"

	"github.com/securego/gosec/v2"
)

const (
	// EffortMinutes effort to fix in minutes
	EffortMinutes = 5
)

// GenerateReport Convert a gosec report to a Sonar Report
func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) {
	si := &Report{Issues: []*Issue{}}
	for _, issue := range data.Issues {
		sonarFilePath := parseFilePath(issue, rootPaths)

		if sonarFilePath == "" {
			continue
		}

		textRange, err := parseTextRange(issue)
		if err != nil {
			return si, err
		}

		primaryLocation := NewLocation(issue.What, sonarFilePath, textRange)
		severity := getSonarSeverity(issue.Severity.String())

		s := NewIssue("gosec", issue.RuleID, primaryLocation, "VULNERABILITY", severity, EffortMinutes)
		si.Issues = append(si.Issues, s)
	}
	return si, nil
}

func parseFilePath(issue *gosec.Issue, rootPaths []string) string {
	var sonarFilePath string
	for _, rootPath := range rootPaths {
		if strings.HasPrefix(issue.File, rootPath) {
			sonarFilePath = strings.Replace(issue.File, rootPath+"/", "", 1)
		}
	}
	return sonarFilePath
}

func parseTextRange(issue *gosec.Issue) (*TextRange, error) {
	lines := strings.Split(issue.Line, "-")
	startLine, err := strconv.Atoi(lines[0])
	if err != nil {
		return nil, err
	}
	endLine := startLine
	if len(lines) > 1 {
		endLine, err = strconv.Atoi(lines[1])
		if err != nil {
			return nil, err
		}
	}
	return NewTextRange(startLine, endLine), nil
}

func getSonarSeverity(s string) string {
	switch s {
	case "LOW":
		return "MINOR"
	case "MEDIUM":
		return "MAJOR"
	case "HIGH":
		return "BLOCKER"
	default:
		return "INFO"
	}
}
