package service

import (
	"context"
	"fmt"
	"opencatd-open/internal/consts"
	"opencatd-open/internal/dao"
	"opencatd-open/internal/model"
	"opencatd-open/internal/utils"
	"strings"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

// var _ TokenService = (*TokenServiceImpl)(nil)

// type TokenService interface {
// }

type TokenServiceImpl struct {
	db        *gorm.DB
	tokenRepo dao.TokenRepository
}

func NewTokenService(db *gorm.DB, tokenRepo dao.TokenRepository) *TokenServiceImpl {
	return &TokenServiceImpl{
		db:        db,
		tokenRepo: tokenRepo,
	}
}

func (t *TokenServiceImpl) CreateToken(ctx context.Context, token *model.Token) error {
	if token.UserID == 0 {
		token.UserID = ctx.Value("user_id").(int64)
	}
	if token.Active == nil {
		token.Active = utils.ToPtr(true)
	}
	if token.UnlimitedQuota == nil {
		token.UnlimitedQuota = utils.ToPtr(true)
	}
	if token.ExpiredAt == nil {
		token.ExpiredAt = utils.ToPtr(int64(-1))
	}

	if token.Key == "" {
		token.Key = "sk-team-" + strings.ReplaceAll(uuid.New().String(), "-", "")
	}
	if !strings.HasPrefix(token.Key, "sk-team-") {
		token.Key = "sk-team-" + strings.ReplaceAll(token.Key, " ", "")
	}
	return t.tokenRepo.Create(ctx, token)
}

func (t *TokenServiceImpl) GetToken(ctx context.Context, id int64) (*model.Token, error) {
	userid := ctx.Value("user_id").(int64)
	tk := &model.Token{}
	return tk, t.db.Model(&model.Token{}).Where("user_id = ?", userid).Where("id = ?", id).First(tk).Error
}

func (t *TokenServiceImpl) ListToken(ctx context.Context, limit, offset int, active []string) ([]*model.Token, int64, error) {
	userid := ctx.Value("user_id").(int64)
	condition := make(map[string]interface{})
	condition["user_id = ?"] = userid
	if len(active) > 0 {
		condition["active IN ?"] = utils.StringToBool(active)
		return t.tokenRepo.ListWithFilters(ctx, limit, offset, condition)
	}
	return t.tokenRepo.ListWithFilters(ctx, limit, offset, condition)
}

func (t *TokenServiceImpl) UpdateToken(ctx context.Context, token *model.Token) error {
	userid := ctx.Value("user_id").(int64) // 操作者
	userRoleValue := ctx.Value("user_role")
	if userRoleValue == nil {
		return fmt.Errorf("user role not found in context")
	}

	role, ok := userRoleValue.(*consts.UserRole) // 操作角色
	if !ok {
		return fmt.Errorf("user role in context is not an integer")
	}

	switch {
	case *role < consts.RoleAdmin:
		if userid != token.UserID {
			return fmt.Errorf("Permission denied")
		}
	case *role == consts.RoleAdmin:
		if *role <= *token.User.Role {
			return fmt.Errorf("Permission denied")
		}
	}

	return t.db.Model(&model.Token{}).Where("id = ?", token.ID).Updates(token).Error
}

func (t *TokenServiceImpl) ResetToken(ctx context.Context, id int64) error {
	userid := ctx.Value("user_id").(int64) // 操作者
	userRoleValue := ctx.Value("user_role")
	if userRoleValue == nil {
		return fmt.Errorf("user role not found in context")
	}

	role, ok := userRoleValue.(*consts.UserRole) // 操作角色
	if !ok {
		return fmt.Errorf("user role in context is not an integer")
	}
	switch {
	case *role < consts.RoleAdmin:
		if userid != id {
			return fmt.Errorf("Permission denied")
		}
	case *role == consts.RoleAdmin:
		var user = &model.User{}
		if err := t.db.Model(&model.User{}).Where("id = ?", id).First(user).Error; err != nil {
			return fmt.Errorf("User not found")
		}
		if *role <= *user.Role {
			return fmt.Errorf("Permission denied")
		}
	}

	token := "sk-team-" + strings.ReplaceAll(uuid.New().String(), "-", "")
	return t.db.Model(&model.Token{}).Where("user_id = ?", userid).Where("id = ?", id).Update("token", token).Error
}
func (t *TokenServiceImpl) DeleteToken(ctx context.Context, id int64) error {
	token, err := t.tokenRepo.GetByID(ctx, id)
	if err != nil {
		return fmt.Errorf("Token not found")
	}
	if token.User == nil {
		return fmt.Errorf("Token user not found")
	}

	role := ctx.Value("user_role").(*consts.UserRole) // 操作角色
	userid := ctx.Value("user_id").(int64)            // 操作者

	switch {
	case *role < consts.RoleAdmin:
		if userid != token.UserID {
			return fmt.Errorf("Permission denied")
		}
	case *role == consts.RoleAdmin:
		if *role <= *token.User.Role {
			return fmt.Errorf("Permission denied")
		}
	}

	return t.db.Model(&model.Token{}).Where("id = ?", id).Delete(&model.Token{}).Error
}

func (t *TokenServiceImpl) DeleteTokens(ctx context.Context, userid int64, ids []int64) error {
	operator_id := ctx.Value("user_id").(int64)

	roleValue := ctx.Value("user_role")
	if roleValue == nil {
		return fmt.Errorf("user role not found in context")
	}
	operator_role, ok := roleValue.(*consts.UserRole) // 操作角色
	if !ok {
		return fmt.Errorf("user role in context is not an integer")
	}

	switch {
	case *operator_role < consts.RoleAdmin:
		if operator_id != userid {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchDelete(ctx, ids, map[string]interface{}{"name != ?": "default", "user_id = ?": userid})
	case *operator_role == consts.RoleAdmin:
		var user = &model.User{}
		if err := t.db.Model(&model.User{}).Where("id = ?", userid).First(user).Error; err != nil {
			return fmt.Errorf("User not found")
		}
		if *operator_role <= *user.Role {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchDelete(ctx, ids, map[string]interface{}{"name != ?": "default", "user_id = ?": userid})
	default:
		return t.tokenRepo.BatchDelete(ctx, ids, map[string]interface{}{"name != ?": "default"})
	}

}

func (t *TokenServiceImpl) EnableTokens(ctx context.Context, userid int64, ids []int64) error {
	operator_id := ctx.Value("user_id").(int64)

	roleValue := ctx.Value("user_role")
	if roleValue == nil {
		return fmt.Errorf("user role not found in context")
	}
	operator_role, ok := roleValue.(*consts.UserRole) // 操作角色
	if !ok {
		return fmt.Errorf("user role in context is not an integer")
	}

	switch {
	case *operator_role < consts.RoleAdmin:
		if operator_id != userid {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchEnable(ctx, ids, map[string]interface{}{"user_id = ?": userid})
	case *operator_role == consts.RoleAdmin:
		var user = &model.User{}
		if err := t.db.Model(&model.User{}).Where("id = ?", userid).First(user).Error; err != nil {
			return fmt.Errorf("User not found")
		}
		if *operator_role <= *user.Role {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchEnable(ctx, ids, map[string]interface{}{"user_id = ?": userid})
	default:
		return t.tokenRepo.BatchEnable(ctx, ids, nil)
	}

}

func (t *TokenServiceImpl) DisableTokens(ctx context.Context, userid int64, ids []int64) error {
	operator_id := ctx.Value("user_id").(int64)

	roleValue := ctx.Value("user_role")
	if roleValue == nil {
		return fmt.Errorf("user role not found in context")
	}
	operator_role, ok := roleValue.(*consts.UserRole) // 操作角色
	if !ok {
		return fmt.Errorf("user role in context is not an integer")
	}

	switch {
	case *operator_role < consts.RoleAdmin:
		if operator_id != userid {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchDisable(ctx, ids, map[string]interface{}{"user_id =": userid})
	case *operator_role == consts.RoleAdmin:
		var user = &model.User{}
		if err := t.db.Model(&model.User{}).Where("id = ?", userid).First(user).Error; err != nil {
			return fmt.Errorf("User not found")
		}
		if *operator_role <= *user.Role {
			return fmt.Errorf("Permission denied")
		}
		return t.tokenRepo.BatchDisable(ctx, ids, map[string]interface{}{"user_id =": userid})
	default:
		return t.tokenRepo.BatchDisable(ctx, ids, nil)
	}

}
