// SPDX-FileCopyrightText: 2025 SAP SE or an SAP affiliate company and Greenhouse contributors
// SPDX-License-Identifier: Apache-2.0

package baseResolver

import (
	"context"

	"github.com/cloudoperators/heureka/internal/api/graphql/graph/model"
	"github.com/cloudoperators/heureka/internal/app"
	"github.com/cloudoperators/heureka/internal/entity"
	"github.com/samber/lo"
	"github.com/sirupsen/logrus"
)

// VulnerabilityBaseResolver retrieves a list of vulnerabilities based on the provided filter and pagination parameters.
// It's designed for the Vulnerability List View in the UI
// - Only returns Issues of type Vulnerability
// - Only returns Issues with at least one IssueMatch with status "new"
// - Default ordering is by IssueVariantRating (descending) and IssuePrimaryName (ascending)
func VulnerabilityBaseResolver(app app.Heureka, ctx context.Context, filter *model.VulnerabilityFilter, first *int, after *string, parent *model.NodeParent) (*model.VulnerabilityConnection, error) {
	requestedFields := GetPreloads(ctx)
	logrus.WithFields(logrus.Fields{
		"requestedFields": requestedFields,
	}).Debug("Called VulnerabilityBaseResolver")

	if filter == nil {
		filter = &model.VulnerabilityFilter{}
	}

	f := &entity.IssueFilter{
		PaginatedX:         entity.PaginatedX{First: first, After: after},
		SupportGroupCCRN:   filter.SupportGroup,
		ServiceCCRN:        filter.Service,
		Type:               []*string{lo.ToPtr(entity.IssueTypeVulnerability.String())},
		Search:             filter.Search,
		HasIssueMatches:    true,
		IssueMatchStatus:   []*string{lo.ToPtr(entity.IssueMatchStatusValuesNew.String())},
		IssueMatchSeverity: lo.Map(filter.Severity, func(item *model.SeverityValues, _ int) *string { return lo.ToPtr(item.String()) }),
		PrimaryName:        filter.Name,
	}

	if parent != nil {
		parentId := parent.Parent.GetID()
		pid, err := ParseCursor(&parentId)
		if err != nil {
			logrus.WithField("parent", parent).Error("VulnerabilityBaseResolver: Error while parsing propagated parent ID'")
			return nil, NewResolverError("VulnerabilityBaseResolver", "Bad Request - Error while parsing propagated ID")
		}
		switch parent.ParentName {
		case model.ImageNodeName:
			f.ComponentId = []*int64{pid}
		}
	}

	opt := GetIssueListOptions(requestedFields)
	// Set default ordering
	opt.Order = append(opt.Order, entity.Order{
		By:        entity.IssueVariantRating,
		Direction: entity.OrderDirectionDesc,
	})
	opt.Order = append(opt.Order, entity.Order{
		By:        entity.IssuePrimaryName,
		Direction: entity.OrderDirectionAsc,
	})

	issues, err := app.ListIssues(f, opt)

	if err != nil {
		return nil, NewResolverError("VulnerabilityBaseResolver", err.Error())
	}

	edges := []*model.VulnerabilityEdge{}
	for _, result := range issues.Elements {
		vulnerability := model.NewVulnerability(result.Issue)
		edge := model.VulnerabilityEdge{
			Node:   &vulnerability,
			Cursor: result.Cursor(),
		}
		edges = append(edges, &edge)
	}

	totalCount := 0
	if issues.TotalCount != nil {
		totalCount = int(*issues.TotalCount)
	}

	connection := model.VulnerabilityConnection{
		TotalCount: totalCount,
		Edges:      edges,
		PageInfo:   model.NewPageInfo(issues.PageInfo),
	}

	if lo.Contains(requestedFields, "counts") {
		icFilter := &model.IssueFilter{
			SupportGroupCcrn: filter.SupportGroup,
			IssueType:        []*model.IssueTypes{lo.ToPtr(model.IssueTypesVulnerability)},
			IssueMatchStatus: []*model.IssueMatchStatusValues{lo.ToPtr(model.IssueMatchStatusValuesNew)},
			Search:           filter.Search,
			ServiceCcrn:      filter.Service,
			AllServices:      lo.ToPtr(true),
		}
		severityCounts, err := IssueCountsBaseResolver(app, ctx, icFilter, &model.NodeParent{
			ParentName: model.VulnerabilityNodeName,
		})
		if err != nil {
			return nil, NewResolverError("VulnerabilityBaseResolver", err.Error())
		}
		connection.Counts = severityCounts
	}

	return &connection, nil
}
