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 CreateUser(ctx context.Context, user models.User) (models.User, error) {

	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "CreateUser")
	defer span.End()

	localLogger = localLogger.WithFields(log.Fields{
		"user_id": user.ID,
	})

	span.SetAttributes(
		attribute.String("user_id", string(user.ID)),
	)

	utils.HandleEvent(span, localLogger, "Starting user creation")

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

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

	utils.HandleEvent(span, localLogger, "User created successfully")
	return user, nil
}

func GetUserByID(ctx context.Context, id models.UserID) (models.User, error) {
	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "GetUserByID")
	defer span.End()

	span.SetAttributes(
		attribute.String("user_id", string(id)),
	)

	localLogger = localLogger.WithFields(log.Fields{
		"user_id": id,
	})

	utils.HandleEvent(span, localLogger, "Starting user retrieval")

	var user models.User

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

	result := client.WithContext(ctx).First(&user, "id = ?", id)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return models.User{}, utils.HandleError(ctx, span, localLogger, &otterError.Database{Reason: otterError.NoDataFound})
		}
		return models.User{}, utils.HandleError(ctx, span, localLogger, result.Error)
	}

	utils.HandleEvent(span, localLogger, "User retrieved successfully")
	return user, nil
}

func DeleteUser(ctx context.Context, id models.UserID, hardDelete bool) error {
	ctx, span, localLogger := utils.SetupTracing(ctx, tracer, "DeleteUser")
	defer span.End()

	span.SetAttributes(
		attribute.String("user_id", string(id)),
	)

	localLogger = localLogger.WithFields(log.Fields{
		"user_id": id,
	})

	utils.HandleEvent(span, localLogger, "Starting user deletion")

	var user models.User

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

	db := client

	if hardDelete {
		db = client.Unscoped()
	} else {
		db = client
	}

	result := db.WithContext(ctx).Delete(&user, id)
	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, "User deleted successfully")
	return nil
}