package repository

import (
	"context"

	"gorm.io/gorm"

	vulnmodel "security-center-backend/internal/modules/vuln/model"
)

type SourceListParams struct {
	Page       int
	PageSize   int
	Query      string
	SystemOnly *bool
}

type SourceRepository interface {
	List(ctx context.Context, params SourceListParams) ([]vulnmodel.Source, int64, error)
	Create(ctx context.Context, source *vulnmodel.Source) error
	Update(ctx context.Context, source *vulnmodel.Source) error
	Delete(ctx context.Context, id uint64) error
	IsSystem(ctx context.Context, id uint64) (bool, error)
}

type GormSourceRepository struct {
	db *gorm.DB
}

func NewSourceRepository(db *gorm.DB) SourceRepository {
	return &GormSourceRepository{db: db}
}

func (r *GormSourceRepository) List(ctx context.Context, params SourceListParams) ([]vulnmodel.Source, int64, error) {
	page := params.Page
	if page <= 0 {
		page = 1
	}
	pageSize := params.PageSize
	if pageSize <= 0 || pageSize > 200 {
		pageSize = 20
	}
	query := r.db.WithContext(ctx).Model(&vulnmodel.Source{})
	if params.Query != "" {
		like := "%" + params.Query + "%"
		query = query.Where("name LIKE ? OR label LIKE ? OR description LIKE ?", like, like, like)
	}
	if params.SystemOnly != nil {
		query = query.Where("is_system = ?", *params.SystemOnly)
	}

	var total int64
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if total == 0 {
		return []vulnmodel.Source{}, 0, nil
	}

	var items []vulnmodel.Source
	if err := query.Order("updated_at DESC").Limit(pageSize).Offset((page - 1) * pageSize).Find(&items).Error; err != nil {
		return nil, 0, err
	}
	return items, total, nil
}

func (r *GormSourceRepository) Create(ctx context.Context, source *vulnmodel.Source) error {
	return r.db.WithContext(ctx).Create(source).Error
}

func (r *GormSourceRepository) Update(ctx context.Context, source *vulnmodel.Source) error {
	updates := map[string]interface{}{
		"name":        source.Name,
		"label":       source.Label,
		"description": source.Description,
	}
	return r.db.WithContext(ctx).Model(&vulnmodel.Source{}).Where("id = ?", source.ID).Updates(updates).Error
}

func (r *GormSourceRepository) Delete(ctx context.Context, id uint64) error {
	return r.db.WithContext(ctx).Delete(&vulnmodel.Source{}, id).Error
}

func (r *GormSourceRepository) IsSystem(ctx context.Context, id uint64) (bool, error) {
	var record vulnmodel.Source
	if err := r.db.WithContext(ctx).Select("id", "is_system").Where("id = ?", id).First(&record).Error; err != nil {
		return false, err
	}
	return record.IsSystem, nil
}
