package repository

import (
	"context"
	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
	"github.com/go-nunu/nunu-layout-advanced/internal/model"
)

type GameShieldBackendRepository interface {
	GetGameShieldBackendById(ctx context.Context, id int64) (*model.GameShieldBackend, error)
	AddGameShieldBackend(ctx context.Context, req *model.GameShieldBackend) error
	EditGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendRequest) error
	DeleteGameShieldBackend(ctx context.Context, id int, hostId int) error
	GetGameShieldBackendByHostId(ctx context.Context, hostId int) ([]model.GameShieldBackend, error)
	GetGameShieldBackendConfigCountByHostId(ctx context.Context, hostId int) (*v1.GameShieldHostBackendConfigResponse, error)
	GetGameShieldBackendSourceMachineIpByHostId(ctx context.Context, hostId int) ([]string, error)
	GetGameShieldBackendByHostIdAndSourceMachineIp(ctx context.Context, hostId int, sourceMachineIp string) ([]model.GameShieldBackend, error)
}

func NewGameShieldBackendRepository(
	repository *Repository,
) GameShieldBackendRepository {
	return &gameShieldBackendRepository{
		Repository: repository,
	}
}

type gameShieldBackendRepository struct {
	*Repository
}

func (r *gameShieldBackendRepository) GetGameShieldBackendById(ctx context.Context, id int64) (*model.GameShieldBackend, error) {
	var gameShieldBackend model.GameShieldBackend
	if err := r.DB(ctx).Where("id = ?", id).First(&gameShieldBackend).Error; err != nil {
		return nil, err
	}
	return &gameShieldBackend, nil
}

func (r *gameShieldBackendRepository) AddGameShieldBackend(ctx context.Context, req *model.GameShieldBackend) error {
	if err := r.DB(ctx).Create(&req).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldBackendRepository) EditGameShieldBackend(ctx context.Context, req *v1.GameShieldBackendRequest) error {
	if err := r.DB(ctx).Model(&model.GameShieldBackend{}).Where("id = ?", req.Id).Updates(req).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldBackendRepository) DeleteGameShieldBackend(ctx context.Context, id int, hostId int) error {
	if err := r.DB(ctx).Where("id = ? AND host_id = ?", id, hostId).Delete(&model.GameShieldBackend{}).Error; err != nil {
		return err
	}
	return nil
}

func (r *gameShieldBackendRepository) GetGameShieldBackendByHostId(ctx context.Context, hostId int) ([]model.GameShieldBackend, error) {
	var gameShieldBackend []model.GameShieldBackend
	if err := r.DB(ctx).Where("host_id = ?", hostId).Order("key_sort DESC").Find(&gameShieldBackend).Error; err != nil {
		return nil, err
	}
	return gameShieldBackend, nil
}

func (r *gameShieldBackendRepository) GetGameShieldBackendConfigCountByHostId(ctx context.Context, hostId int) (*v1.GameShieldHostBackendConfigResponse, error) {
	var res v1.GameShieldHostBackendConfigResponse
	if err := r.DB(ctx).Model(&model.GameShieldBackend{}).Where("host_id = ?", hostId).Count(&res.RuleEntriesCount).Error; err != nil {
		return nil, err
	}
	if err := r.DB(ctx).Model(&model.GameShieldBackend{}).Where("host_id = ?", hostId).Distinct("source_machine_ip").Count(&res.SourceMachinesCount).Error; err != nil {
		return nil, err
	}
	if err := r.DB(ctx).Model(&model.GameShieldBackend{}).Where("host_id = ?", hostId).Where("max_bandwidth = ?", 1).Count(&res.MaxBandwidthCount).Error; err != nil {
		return nil, err
	}
	return &res, nil
}

func (r *gameShieldBackendRepository) GetGameShieldBackendSourceMachineIpByHostId(ctx context.Context, hostId int) ([]string, error) {
	var res []string
	if err := r.DB(ctx).Model(&model.GameShieldBackend{}).Where("host_id = ?", hostId).Distinct("source_machine_ip").Pluck("source_machine_ip", &res).Error; err != nil {
		return nil, err
	}
	return res, nil
}

func (r *gameShieldBackendRepository) GetGameShieldBackendByHostIdAndSourceMachineIp(ctx context.Context, hostId int, sourceMachineIp string) ([]model.GameShieldBackend, error) {
	var res []model.GameShieldBackend
	if err := r.DB(ctx).Where("host_id = ? AND source_machine_ip = ?", hostId, sourceMachineIp).Find(&res).Error; err != nil {
		return nil, err
	}
	return res, nil
}
