package service

import (
	"context"
	"time"

	vulnmodel "vul-backend/internal/modules/vuln/model"
	"vul-backend/internal/modules/vuln/repository"
)

type Service struct {
	repo        repository.VulnerabilityRepository
	channelRepo repository.DiscoveryChannelRepository
}

type Configuration struct {
	SeverityLevels    []string                `json:"severity_levels"`
	DiscoveryChannels []string                `json:"discovery_channels"`
	DiscoveryPhases   []string                `json:"discovery_phases"`
	NetworkEnvs       []string                `json:"network_envs"`
	Types             []VulnerabilityTypeInfo `json:"types"`
}

type VulnerabilityTypeInfo struct {
	Name            string `json:"name"`
	Category        string `json:"category"`
	DefaultSeverity string `json:"default_severity"`
	Description     string `json:"description"`
}

type ListQuery struct {
	Page              int
	PageSize          int
	Statuses          []vulnmodel.VulnerabilityStatus
	Severities        []vulnmodel.SeverityLevel
	OwnerID           *uint64
	SubmitterID       *uint64
	Application       string
	BusinessDept      string
	DiscoveryPhase    string
	DiscoveryChannel  string
	NetworkEnv        string
	HasPOC            *bool
	IsOverdue         *bool
	IsThirdParty      *bool
	Tags              []string
	DependencyName    string
	DependencyVersion string
	BatchGroupID      *uint64
	HasBatchGroup     *bool
	Keyword           string
	SubmittedFrom     *time.Time
	SubmittedTo       *time.Time
	SortBy            string
	SortOrder         string
}

type ListResult struct {
	Items    []vulnmodel.Vulnerability
	Total    int64
	Page     int
	PageSize int
}

func New(repo repository.VulnerabilityRepository, channelRepo repository.DiscoveryChannelRepository) *Service {
	return &Service{repo: repo, channelRepo: channelRepo}
}

func (s *Service) List(ctx context.Context, query ListQuery) (*ListResult, error) {
	if s.repo == nil {
		return &ListResult{}, nil
	}

	items, total, err := s.repo.List(ctx, repository.ListParams{
		Page:              query.Page,
		PageSize:          query.PageSize,
		Statuses:          query.Statuses,
		Severities:        query.Severities,
		OwnerID:           query.OwnerID,
		SubmitterID:       query.SubmitterID,
		Application:       query.Application,
		BusinessDept:      query.BusinessDept,
		DiscoveryPhase:    query.DiscoveryPhase,
		DiscoveryChannel:  query.DiscoveryChannel,
		NetworkEnv:        query.NetworkEnv,
		HasPOC:            query.HasPOC,
		IsOverdue:         query.IsOverdue,
		IsThirdParty:      query.IsThirdParty,
		Tags:              query.Tags,
		DependencyName:    query.DependencyName,
		DependencyVersion: query.DependencyVersion,
		BatchGroupID:      query.BatchGroupID,
		HasBatchGroup:     query.HasBatchGroup,
		Keyword:           query.Keyword,
		SubmittedFrom:     query.SubmittedFrom,
		SubmittedTo:       query.SubmittedTo,
		SortBy:            query.SortBy,
		SortOrder:         query.SortOrder,
	})
	if err != nil {
		return nil, err
	}
	return &ListResult{Items: items, Total: total, Page: query.Page, PageSize: query.PageSize}, nil
}

func (s *Service) Create(ctx context.Context, vuln *vulnmodel.Vulnerability) error {
	if s.repo == nil {
		return nil
	}
	return s.repo.Create(ctx, vuln)
}

func (s *Service) GetConfiguration(ctx context.Context) (*Configuration, error) {
	config := &Configuration{
		SeverityLevels:  []string{"critical", "high", "medium", "low"},
		DiscoveryPhases: []string{"pre_release", "post_release"},
		NetworkEnvs:     []string{"internal", "external"},
		Types: []VulnerabilityTypeInfo{
			{
				Name:            "SQL Injection",
				Category:        "Web",
				DefaultSeverity: "high",
				Description:     "Detected by code scanning or manual testing on API endpoints.",
			},
			{
				Name:            "Dependency Vulnerability",
				Category:        "Third-Party",
				DefaultSeverity: "critical",
				Description:     "Imported from dependency advisories (e.g., log4j).",
			},
			{
				Name:            "Business Logic",
				Category:        "Application",
				DefaultSeverity: "medium",
				Description:     "Workflows missing authorization or rate limiting.",
			},
		},
	}

	if s.channelRepo != nil {
		channels, _, err := s.channelRepo.List(ctx, repository.DiscoveryChannelListParams{Page: 1, PageSize: 500})
		if err == nil && len(channels) > 0 {
			config.DiscoveryChannels = make([]string, 0, len(channels))
			for _, ch := range channels {
				config.DiscoveryChannels = append(config.DiscoveryChannels, ch.Label)
			}
		}
	}
	if len(config.DiscoveryChannels) == 0 {
		config.DiscoveryChannels = []string{"white_box", "black_box", "manual_audit", "threat_intel"}
	}

	return config, nil
}
