package system

import (
	"errors"
	"strconv"

	"kra/internal/biz/system"

	"github.com/casbin/casbin/v2"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"gorm.io/gorm"
)

type casbinRepo struct {
	db       *gorm.DB
	enforcer *casbin.SyncedCachedEnforcer
}

// NewCasbinRepo 创建Casbin仓储
func NewCasbinRepo(db *gorm.DB, enforcer *casbin.SyncedCachedEnforcer) system.CasbinRepo {
	return &casbinRepo{db: db, enforcer: enforcer}
}

// ClearCasbin 清除匹配的权限
func (r *casbinRepo) ClearCasbin(v int, p ...string) bool {
	success, _ := r.enforcer.RemoveFilteredPolicy(v, p...)
	return success
}

// UpdateCasbinApi API更新随动
func (r *casbinRepo) UpdateCasbinApi(oldPath, newPath, oldMethod, newMethod string) error {
	err := r.db.Model(&gormadapter.CasbinRule{}).
		Where("v1 = ? AND v2 = ?", oldPath, oldMethod).
		Updates(map[string]any{"v1": newPath, "v2": newMethod}).Error
	if err != nil {
		return err
	}
	return r.enforcer.LoadPolicy()
}

// GetPolicyPathByAuthorityId 获取权限列表
func (r *casbinRepo) GetPolicyPathByAuthorityId(authorityId uint) []system.CasbinRule {
	authorityIdStr := strconv.FormatUint(uint64(authorityId), 10)
	list, _ := r.enforcer.GetFilteredPolicy(0, authorityIdStr)
	pathMaps := make([]system.CasbinRule, len(list))
	for i, v := range list {
		pathMaps[i] = system.CasbinRule{
			Path:   v[1],
			Method: v[2],
		}
	}
	return pathMaps
}

// FreshCasbin 刷新Casbin缓存
func (r *casbinRepo) FreshCasbin() error {
	return r.enforcer.LoadPolicy()
}

// AddPolicies 添加策略（使用数据库方法）
func (r *casbinRepo) AddPolicies(rules [][]string) error {
	if len(rules) == 0 {
		return nil
	}
	casbinRules := make([]gormadapter.CasbinRule, len(rules))
	for i, rule := range rules {
		casbinRules[i] = gormadapter.CasbinRule{
			Ptype: "p",
			V0:    rule[0],
			V1:    rule[1],
			V2:    rule[2],
		}
	}
	return r.db.Create(&casbinRules).Error
}

// UpdateCasbin 更新Casbin权限
func (r *casbinRepo) UpdateCasbin(adminAuthorityID, authorityId uint, casbinInfos []system.CasbinRule) error {
	authorityIdStr := strconv.FormatUint(uint64(authorityId), 10)

	// 清除旧权限
	r.ClearCasbin(0, authorityIdStr)

	// 去重处理
	deduplicateMap := make(map[string]bool)
	var rules [][]string
	for _, v := range casbinInfos {
		key := authorityIdStr + v.Path + v.Method
		if !deduplicateMap[key] {
			deduplicateMap[key] = true
			rules = append(rules, []string{authorityIdStr, v.Path, v.Method})
		}
	}

	if len(rules) == 0 {
		return nil
	}

	// 使用enforcer添加策略
	success, _ := r.enforcer.AddPolicies(rules)
	if !success {
		return errors.New("存在相同api,添加失败,请联系管理员")
	}
	return nil
}

// RemoveFilteredPolicy 删除筛选的策略
func (r *casbinRepo) RemoveFilteredPolicy(authorityId string) error {
	return r.db.Delete(&gormadapter.CasbinRule{}, "v0 = ?", authorityId).Error
}

// SyncPolicy 同步策略（先删除再添加）
func (r *casbinRepo) SyncPolicy(authorityId string, rules [][]string) error {
	// 先删除旧策略
	if err := r.RemoveFilteredPolicy(authorityId); err != nil {
		return err
	}
	// 再添加新策略
	return r.AddPolicies(rules)
}
