package repository

import (
	"context"
	"errors"

	"github.com/tidbcloud/pkgv2/db"
	"gorm.io/gorm"

	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/repository/schema"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

type OrganizationRuConfigRepoImpl struct {
	dbProvider db.Provider
}

func NewOrganizationRuConfigRepo(dbProvider db.Provider) repository.OrganizationRuConfigRepository {
	return &OrganizationRuConfigRepoImpl{dbProvider: dbProvider}
}

func (r *OrganizationRuConfigRepoImpl) GetByOrganizationId(ctx context.Context, organizationId uint64) (*entity.OrganizationRuConfig, error) {
	ctx, span := tracer.Start(ctx, "OrganizationRuConfigRepo.GetByOrganizationId")
	defer span.End()

	if organizationId == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "organization_id is required")
	}

	rdb := r.dbProvider.ReadDB(ctx)
	var m schema.OrganizationRuConfig
	if err := rdb.Where("organization_id = ?", organizationId).First(&m).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return &entity.OrganizationRuConfig{
				OrganizationID:   organizationId,
				DefaultRuVersion: repository.SystemDefaultRuVersion,
			}, nil
		}
		return nil, bizerr.WrapGormError(err, "failed to get organization ru config")
	}

	return &entity.OrganizationRuConfig{
		OrganizationID:   m.OrganizationID,
		DefaultRuVersion: m.DefaultRuVersion,
	}, nil
}

func (r *OrganizationRuConfigRepoImpl) Upsert(ctx context.Context, config *entity.OrganizationRuConfig) error {
	ctx, span := tracer.Start(ctx, "OrganizationRuConfigRepo.Upsert")
	defer span.End()

	if config == nil {
		return bizerr.New(bizerr.ErrCodeParams, "config is nil")
	}
	if config.OrganizationID == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "organization_id is required")
	}

	wdb := r.dbProvider.WriteDB(ctx)

	var existing schema.OrganizationRuConfig
	err := wdb.Where("organization_id = ?", config.OrganizationID).First(&existing).Error
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return bizerr.WrapGormError(err, "failed to query organization ru config")
	}

	if errors.Is(err, gorm.ErrRecordNotFound) {
		// Create new record
		m := &schema.OrganizationRuConfig{
			OrganizationID:   config.OrganizationID,
			DefaultRuVersion: config.DefaultRuVersion,
		}
		if err := wdb.Create(m).Error; err != nil {
			return bizerr.WrapGormError(err, "failed to create organization ru config")
		}
	} else {
		// Update existing record
		if err := wdb.Model(&existing).Update("default_ru_version", config.DefaultRuVersion).Error; err != nil {
			return bizerr.WrapGormError(err, "failed to update organization ru config")
		}
	}

	return nil
}
