package repository

import (
	"context"
	"errors"

	"gorm.io/gorm"

	"security-center-backend/internal/model"
)

var ErrSettingsVersionConflict = errors.New("system settings version mismatch")

type SystemSettingsRepository interface {
	Get(ctx context.Context) (*model.SystemSettings, error)
	Create(ctx context.Context, settings *model.SystemSettings) (*model.SystemSettings, error)
	Update(ctx context.Context, settings *model.SystemSettings, expectedVersion uint64) (*model.SystemSettings, error)
}

type GormSystemSettingsRepository struct {
	db *gorm.DB
}

func NewSystemSettingsRepository(db *gorm.DB) SystemSettingsRepository {
	return &GormSystemSettingsRepository{db: db}
}

func (r *GormSystemSettingsRepository) Get(ctx context.Context) (*model.SystemSettings, error) {
	var settings model.SystemSettings
	if err := r.db.WithContext(ctx).First(&settings).Error; err != nil {
		return nil, err
	}
	return &settings, nil
}

func (r *GormSystemSettingsRepository) Create(ctx context.Context, settings *model.SystemSettings) (*model.SystemSettings, error) {
	if err := r.db.WithContext(ctx).Create(settings).Error; err != nil {
		return nil, err
	}
	return settings, nil
}

func (r *GormSystemSettingsRepository) Update(ctx context.Context, settings *model.SystemSettings, expectedVersion uint64) (*model.SystemSettings, error) {
	if settings == nil {
		return nil, errors.New("settings payload required")
	}
	settings.Version = expectedVersion + 1
	tx := r.db.WithContext(ctx).Model(&model.SystemSettings{}).
		Where("id = ? AND version = ?", settings.ID, expectedVersion).
		Updates(map[string]interface{}{
			"platform":       settings.Platform,
			"authentication": settings.Authentication,
			"notifications":  settings.Notifications,
			"data_sync":      settings.DataSync,
			"updated_by":     settings.UpdatedBy,
			"version":        settings.Version,
		})
	if tx.Error != nil {
		return nil, tx.Error
	}
	if tx.RowsAffected == 0 {
		return nil, ErrSettingsVersionConflict
	}
	var updated model.SystemSettings
	if err := r.db.WithContext(ctx).First(&updated, settings.ID).Error; err != nil {
		return nil, err
	}
	return &updated, nil
}
