package database

import (
	"context"
	"errors"

	"git.anthrove.art/Anthrove/otter-space-sdk/v6/internal/utils"
	otterError "git.anthrove.art/Anthrove/otter-space-sdk/v6/pkg/error"
	"git.anthrove.art/Anthrove/otter-space-sdk/v6/pkg/models"
	log "github.com/sirupsen/logrus"
	"go.opentelemetry.io/otel/attribute"
	"gorm.io/gorm"
)

func CreateTagAlias(ctx context.Context, tagAliasName models.TagAliasName, tagID models.TagID) (models.TagAlias, error) {
	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagAlias")
	defer span.End()

	localLogger = localLogger.WithFields(log.Fields{
		"tag_alias_name": tagAliasName,
		"tag_id":         tagID,
	})

	span.SetAttributes(
		attribute.String("tag_alias_name", string(tagAliasName)),
		attribute.Int64("tag_id", int64(tagID)),
	)

	utils.HandleEvent(span, localLogger, "Starting tag alias creation")

	if client == nil {
		return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
	}

	if tagAliasName == "" {
		return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.TagAliasNameIsEmpty})
	}

	tagAlias := models.TagAlias{
		Name:  tagAliasName,
		TagID: tagID,
	}

	result := client.WithContext(ctx).Create(&tagAlias)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
			return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
		}
		return models.TagAlias{}, utils.HandleError(ctx, span, localLogger, result.Error)
	}

	utils.HandleEvent(span, localLogger, "Tag alias created successfully")
	return tagAlias, nil
}

func CreateTagAliasInBatch(ctx context.Context, tagsAliases []models.TagAlias, batchSize int) error {
	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateTagAliasInBatch")
	defer span.End()

	localLogger = localLogger.WithFields(log.Fields{
		"tag_aliases_count": len(tagsAliases),
		"batch_size":        batchSize,
	})

	span.SetAttributes(
		attribute.Int("batch_size", batchSize),
		attribute.Int("tag_aliases_count", len(tagsAliases)),
	)

	utils.HandleEvent(span, localLogger, "Starting batch tag alias creation")

	if client == nil {
		return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
	}

	if tagsAliases == nil || len(tagsAliases) == 0 {
		return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.TagAliasListIsEmpty})
	}

	if batchSize == 0 {
		return utils.HandleError(ctx, span, localLogger, &otterError.EntityValidationFailed{Reason: otterError.BatchSizeIsEmpty})
	}

	result := client.WithContext(ctx).CreateInBatches(&tagsAliases, batchSize)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrDuplicatedKey) {
			return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DuplicateKey})
		}
		return utils.HandleError(ctx, span, localLogger, result.Error)
	}

	utils.HandleEvent(span, localLogger, "Batch tags aliases created successfully")
	return nil
}

func DeleteTagAlias(ctx context.Context, tagAliasID models.TagAliasID) error {
	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteTagAlias")
	defer span.End()

	localLogger = localLogger.WithFields(log.Fields{
		"tag_alias_id": tagAliasID,
	})

	span.SetAttributes(
		attribute.Int64("tag_alias_id", int64(tagAliasID)),
	)

	utils.HandleEvent(span, localLogger, "Starting tag alias deletion")

	var tagAlias models.TagAlias

	if client == nil {
		return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.DatabaseIsNotConnected})
	}

	result := client.WithContext(ctx).Delete(&tagAlias, tagAliasID)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
		}
		return utils.HandleError(ctx, span, localLogger, result.Error)
	}

	utils.HandleEvent(span, localLogger, "Tag alias deleted successfully")
	return nil
}