package myCasbin

import (
	"context"
	"server/internal/consts"
	"sync"

	"github.com/casbin/casbin/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
	adapter "github.com/hailaz/gf-casbin-adapter/v2"
)

type myCasbin struct {
	*casbin.Enforcer
}

var (
	instance *myCasbin
	once     sync.Once
)

func init() {
	ctx := context.Background()
	once.Do(func() {
		modelPath := g.Config().MustGet(ctx, "casbin.modelPath").String()
		enforcer, err := casbin.NewEnforcer(modelPath, adapter.NewAdapter(
			adapter.Options{
				GDB:       g.DB(),
				FieldName: &adapter.FieldName{PType: "p_type"},
			},
		))
		if err != nil {
			glog.Errorf(ctx, "init casbin error: %v", err)
		}

		enforcer.LoadPolicy()

		enforcer.AddGroupingPolicy(consts.UserRoleCode, consts.GuestRoleCode)
		enforcer.AddGroupingPolicy(consts.AuthorRoleCode, consts.UserRoleCode)
		enforcer.AddGroupingPolicy(consts.AdminRoleCode, consts.AuthorRoleCode)
		// guest
		{
			enforcer.AddPolicy("guest", "/book/app/list", "GET", "App获取书籍列表")
			enforcer.AddPolicy("guest", "/book/app/detail", "GET", "App获取书籍详情")
			enforcer.AddPolicy("guest", "/chapter/app/list", "GET", "App获取章节列表")
			enforcer.AddPolicy("guest", "/chapter/app/detail", "GET", "App获取章节详情")
			enforcer.AddPolicy("guest", "/category", "GET", "获取分类列表")
			enforcer.AddPolicy("guest", "/recommend/app/list", "GET", "App获取推荐列表")
			enforcer.AddPolicy("guest", "/activity/sign", "GET", "用户签到任务列表")
			enforcer.AddPolicy("guest", "/task/appList", "GET", "App端任务列表")
			enforcer.AddPolicy("guest", "/system/version", "GET", "获取系统版本信息")
		}
		//  user
		{
			// book
			enforcer.AddPolicy("user", "/book/shelf/add", "POST", "加入书架")
			enforcer.AddPolicy("user", "/book/shelf/remove", "POST", "移除书架")
			enforcer.AddPolicy("user", "/book/app/rate", "POST", "App用户评分")
			enforcer.AddPolicy("user", "/book/app/my-books", "GET", "获取我的书籍列表")
			// chapter
			enforcer.AddPolicy("user", "/chapter/app/purchase", "POST", "App购买章节")
			enforcer.AddPolicy("user", "/chapter/app/progress", "POST", "App上传阅读进度")
			// feedback
			enforcer.AddPolicy("user", "/feedback", "POST", "新增反馈")
			// user
			enforcer.AddPolicy("user", "/user/info", "GET", "获取用户信息")
			enforcer.AddPolicy("user", "/user/delete", "POST", "删除用户")
			enforcer.AddPolicy("user", "/user/logout", "POST", "用户登出")
			// author follow/unfollow
			enforcer.AddPolicy("user", "/author/follow", "POST", "关注作者")
			enforcer.AddPolicy("user", "/author/unfollow", "POST", "取消关注作者")
			enforcer.AddPolicy("user", "/author/detail", "GET", "获取作者详情")
			enforcer.AddPolicy("user", "/activity/sign", "POST", "用户签到")
			enforcer.AddPolicy("user", "/author/apply", "POST", "申请成为作者")
		}
		// author
		{
			// book
			enforcer.AddPolicy("author", "/book", "GET", "获取图书列表")
			enforcer.AddPolicy("author", "/book", "POST", "新增图书")
			enforcer.AddPolicy("author", "/book", "PUT", "编辑图书")
			enforcer.AddPolicy("author", "/book", "DELETE", "删除图书")
			enforcer.AddPolicy("author", "/book/coverImage", "POST", "上传图书封面图")

			// chapter
			enforcer.AddPolicy("author", "/chapter", "GET", "获取章节列表")
			enforcer.AddPolicy("author", "/chapter", "POST", "创建章节")
			enforcer.AddPolicy("author", "/chapter", "PUT", "更新章节")
			enforcer.AddPolicy("author", "/chapter", "DELETE", "删除章节")

			enforcer.AddPolicy("author", "/author/info", "GET", "获取作者基础信息")
		}
		// admin
		{
			// book
			enforcer.AddPolicy("admin", "/book/set-featured", "POST", "设置书籍精选状态")
			enforcer.AddPolicy("admin", "/book/set-recommended", "POST", "设置书籍推荐状态")
			enforcer.AddPolicy("admin", "/book/set-hot", "POST", "设置书籍最热状态")
			// author
			enforcer.AddPolicy("admin", "/author", "GET", "获取作者列表")
			enforcer.AddPolicy("admin", "/author", "POST", "创建作者")
			enforcer.AddPolicy("admin", "/author", "PUT", "更新作者")
			enforcer.AddPolicy("admin", "/author", "DELETE", "删除作者")
			// feedback
			enforcer.AddPolicy("admin", "/feedback", "GET", "获取反馈列表")
			// category
			enforcer.AddPolicy("admin", "/category", "POST", "创建分类")
			enforcer.AddPolicy("admin", "/category", "PUT", "更新分类")
			enforcer.AddPolicy("admin", "/category", "DELETE", "删除分类")
			// admin
			enforcer.AddPolicy("admin", "/admin/info", "GET", "获取管理员用户信息")
			enforcer.AddPolicy("admin", "/admin/editPass", "POST", "管理员修改密码")
			enforcer.AddPolicy("admin", "/author/review", "POST", "审核作者申请")
			enforcer.AddPolicy("admin", "/task", "GET", "获取任务列表")
			enforcer.AddPolicy("admin", "/task", "POST", "新增任务")
			enforcer.AddPolicy("admin", "/task", "PUT", "编辑任务")
			enforcer.AddPolicy("admin", "/task", "DELETE", "删除任务")
			enforcer.AddPolicy("admin", "/system/save", "POST", "获取系统版本信息")

		}
		// recommend
		{
			enforcer.AddPolicy("admin", "/recommend", "GET", "获取推荐列表")
			enforcer.AddPolicy("admin", "/recommend", "POST", "新增推荐")
			enforcer.AddPolicy("admin", "/recommend", "PUT", "编辑推荐")
			enforcer.AddPolicy("admin", "/recommend", "DELETE", "删除推荐")
			enforcer.AddPolicy("admin", "/recommend/set-status", "POST", "设置推荐状态")
			enforcer.AddPolicy("admin", "/recommend/sort-order", "POST", "设置推荐排序")
			enforcer.AddPolicy("admin", "/recommend/info", "GET", "获取推荐详情")
		}
		// activity 签到奖励规则相关接口
		{
			enforcer.AddPolicy("admin", "/activity", "GET", "获取签到奖励规则全信息")
			enforcer.AddPolicy("admin", "/activity", "POST", "新增签到奖励规则全信息")
			enforcer.AddPolicy("admin", "/activity/*", "PUT", "编辑签到奖励规则全信息")
			enforcer.AddPolicy("admin", "/activity/*", "DELETE", "删除签到奖励规则全信息")
			enforcer.AddPolicy("admin", "/activity/*/status", "PATCH", "设置签到奖励规则状态全信息")
			enforcer.AddPolicy("admin", "/activity/items", "GET", "获取签到奖励明细列表")
			enforcer.AddPolicy("admin", "/activity/item", "POST", "新增签到奖励明细")
			enforcer.AddPolicy("admin", "/activity/item/*", "PUT", "编辑签到奖励明细")
			enforcer.AddPolicy("admin", "/activity/item/*", "DELETE", "删除签到奖励明细")
			enforcer.AddPolicy("admin", "/activity/item/*", "GET", "获取单个签到奖励明细")
			enforcer.AddPolicy("admin", "/activity/item/*/status", "PATCH", "设置签到奖励明细状态")
		}
		instance = &myCasbin{Enforcer: enforcer}

	})
	glog.Infof(ctx, "init casbin success")
}

func GetMyCasbin() *myCasbin {
	if instance == nil {
		panic("casbin not init")
	}
	return instance
}

// HasPermission 判断给定的权限标识是否拥有访问指定 URL 和方法的权限。
//
// 参数:
//   - permission: 权限标识（如角色名或用户 ID）
//   - url: 请求的路径（如 "/api/user/list"）
//   - method: HTTP 请求方法（如 "GET", "POST"）
//
// 返回:
//   - access: 如果有权限则为 true；否则为 false。
//   - 若校验过程中发生错误，将记录日志并返回 false。
func (m *myCasbin) HasPermission(permission, url, method string) (access bool) {
	enforce, err := m.Enforcer.Enforce(permission, url, method)
	if err != nil {
		glog.Errorf(context.Background(), "enforce error: %v", err)
		return
	}
	return enforce
}
