package svc

import (
	"github.com/bwmarrin/snowflake"
	"github.com/zeromicro/go-zero/core/collection"
	"gorm.io/gorm"
	"time"
	"wechat-api/database"
	"wechat-api/database/dao/wechat/query"
	"wechat-api/internal/config"
	"wechat-api/internal/middleware"
	"wechat-api/internal/pkg/wechat_ws"
	"wechat-api/mongo_model"

	"github.com/redis/go-redis/v9"

	"wechat-api/ent"
	_ "wechat-api/ent/runtime"

	"github.com/suyuan32/simple-admin-core/rpc/coreclient"
	"github.com/zeromicro/go-zero/core/logx"

	"github.com/casbin/casbin/v2"
	"github.com/zeromicro/go-zero/rest"
	"github.com/zeromicro/go-zero/zrpc"
)

type ServiceContext struct {
	Config        config.Config
	Casbin        *casbin.Enforcer
	Authority     rest.Middleware
	OpenAuthority rest.Middleware
	Miniprogram   rest.Middleware
	DB            *ent.Client
	WechatDB      *gorm.DB
	WechatQ       *query.Query
	CoreRpc       coreclient.Core
	Rds           redis.UniversalClient
	WechatWs      map[string]*wechat_ws.WechatWsClient
	Cache         *collection.Cache
	NodeID        *snowflake.Node
	MongoModel    *mongo_model.AllMongoModel
}

func NewServiceContext(c config.Config) *ServiceContext {

	rds := c.RedisConf.MustNewUniversalRedis()

	cbn := c.CasbinConf.MustNewCasbinWithOriginalRedisWatcher(c.CasbinDatabaseConf.Type, c.CasbinDatabaseConf.GetDSN(), c.RedisConf)

	db := ent.NewClient(
		ent.Log(logx.Info), // logger
		ent.Driver(c.DatabaseConf.NewNoCacheDriver()),
		ent.Debug(), // debug mode
	)

	// 初始化 MongoDB 客户端
	all_mongo_model := mongo_model.SetupMongoModel(c.FastgptMongoConf.Url, c.FastgptMongoConf.DBName)

	// gorm 数据库连接
	wechatDb, err := database.InitWechatDB(c.DatabaseConf, c.Mode)
	if err != nil {
		logx.Error(err)
		panic("gorm 数据库连接失败")
	}
	wechatQ := query.Use(wechatDb)

	coreRpc := coreclient.NewCore(zrpc.NewClientIfEnable(c.CoreRpc))

	// 初始化微信ws客户端
	// todo 现在配置是从 config.yaml中读取的,后续需要改成从数据库中读取,以便匹配不同的微信号
	wechatWs := make(map[string]*wechat_ws.WechatWsClient)

	for _, ws := range c.WebSocket {
		if ws.Type == "wechat" {
			client, err := wechat_ws.NewWechatWsClient(ws.Url, ws.Name, ws.Type)
			if err != nil {
				logx.Error(err)
			} else {
				logx.Info("建立ws client成功~", ws.Name)
				go client.ReadPump()
				go client.WritePump()
				wechatWs[ws.Name] = client
			}
		}
	}

	cache, err := collection.NewCache(time.Hour * 24 * 365)
	if err != nil {
		logx.Error(err)
		panic("本地缓存实例失败")
	}

	node, err := snowflake.NewNode(1)
	if err != nil {
		logx.Error(err)
		panic("雪花算法实例失败")
	}

	return &ServiceContext{
		Config:        c,
		Authority:     middleware.NewAuthorityMiddleware(cbn, rds, coreRpc).Handle,
		OpenAuthority: middleware.NewOpenAuthorityMiddleware(db, rds, c).Handle,
		Miniprogram:   middleware.NewMiniprogramMiddleware(cbn, rds, coreRpc, c).Handle,
		DB:            db,
		WechatDB:      wechatDb,
		WechatQ:       wechatQ,
		CoreRpc:       coreRpc,
		Rds:           rds,
		WechatWs:      wechatWs,
		Cache:         cache,
		NodeID:        node,
		MongoModel:    all_mongo_model,
	}
}