package user

import (
	"context"
	"time"

	"github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/pkg/xerr"
	"github.com/pkg/errors"
	"gorm.io/gorm"
)

const familyStatusDisabled uint8 = 0

type familyExitHelper struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func newFamilyExitHelper(ctx context.Context, svcCtx *svc.ServiceContext) *familyExitHelper {
	return &familyExitHelper{
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (h *familyExitHelper) removeUserFromActiveFamily(tx *gorm.DB, userID int64, dissolveWhenOwner bool) error {
	var relation user.UserFamilyMember
	err := tx.Unscoped().
		Model(&user.UserFamilyMember{}).
		Where("user_id = ? AND status = ?", userID, user.FamilyMemberActive).
		First(&relation).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
		return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family member relation failed")
	}

	now := time.Now()

	if relation.Role == user.FamilyRoleOwner && dissolveWhenOwner {
		if err = tx.Model(&user.UserFamilyMember{}).
			Where("family_id = ? AND status = ?", relation.FamilyId, user.FamilyMemberActive).
			Updates(map[string]interface{}{
				"status":  user.FamilyMemberRemoved,
				"left_at": now,
			}).Error; err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "remove owner family members failed")
		}

		if err = tx.Model(&user.UserFamily{}).
			Where("id = ?", relation.FamilyId).
			Updates(map[string]interface{}{
				"status": familyStatusDisabled,
			}).Error; err != nil {
			return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "disable owner family failed")
		}
		return nil
	}

	if err = tx.Model(&user.UserFamilyMember{}).
		Where("id = ?", relation.Id).
		Updates(map[string]interface{}{
			"status":  user.FamilyMemberRemoved,
			"left_at": now,
		}).Error; err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "remove family member failed")
	}

	return nil
}
