package svc

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"git.i2edu.net/i2/go-zero/core/stores/sqlx"
	"git.i2edu.net/i2/go-zero/rest/token"
	"git.i2edu.net/i2/go-zero/zrpc"
	"git.i2edu.net/i2/i2-bill-api/internal/config"
	"git.i2edu.net/i2/i2-bill-api/model"
	"git.i2edu.net/i2/i2-bill-erp/transformclient"
	"github.com/dgrijalva/jwt-go"

	_ "github.com/go-sql-driver/mysql"
	"github.com/xormplus/xorm"
)

var ServiceConfig config.Config

type ServiceContext struct {
	Config                     config.Config
	SqlConn                    sqlx.SqlConn
	RdCli                      Cache
	Wechat                     *Wechat
	Transformer                transformclient.Transform
	UserModel                  model.UserModel
	I2billAcquirerStudentModel model.I2billAcquirerStudentModel
	DB                         *xorm.Engine
}

// GetUserId defined TODO
func (sc *ServiceContext) GetClaims(r *http.Request) (int64, string, error) {
	parser := token.NewTokenParser(token.WithResetDuration(time.Minute))
	tok, err := parser.ParseToken(r, sc.Config.JwtAuth.AccessSecret, "")
	if err != nil {
		return 0, "", err
	}
	userId, sessionKey := int64(0), ""
	m := tok.Claims.(jwt.MapClaims)
	switch nbf := m["userId"].(type) {
	case string:
		i, err := strconv.ParseInt(nbf, 10, 64)
		if err != nil {
			return 0, "", err
		}
		userId = i
	case json.Number:
		v, err := nbf.Int64()
		if err != nil {
			return 0, "", err
		}
		userId = v
	}
	switch nbf := m["sessionKey"].(type) {
	case string:
		sessionKey = nbf
	case json.Number:
		v, err := nbf.Int64()
		if err != nil {
			return 0, "", err
		}
		sessionKey = fmt.Sprintf("%v", v)
	}
	return userId, sessionKey, err
}

func (sc *ServiceContext) GetUserIdByJwt(ctx context.Context) int64 {
	UserIdStr := ctx.Value("userId").(json.Number)
	number, _ := strconv.ParseInt(UserIdStr.String(), 10, 64)
	return number
}

func NewServiceContext(c config.Config) *ServiceContext {

	db, err := xorm.NewEngine("mysql", c.DataSource)
	if err != nil {
		panic(err)
	}
	db.RegisterSqlMap(xorm.Xml("sqlconfig", ".xml"))
	db.RegisterSqlTemplate(xorm.Pongo2("sqlconfig", ".stpl"))
	db.RegisterSqlTemplate(xorm.Jet("sqlconfig", ".jet"))
	db.RegisterSqlTemplate(xorm.Default("sqlconfig", ".tpl"))
	db.ShowSQL(true)
	svc := &ServiceContext{
		Config:      c,
		SqlConn:     sqlx.NewMysql(c.DataSource),
		Transformer: transformclient.NewTransform(zrpc.MustNewClient(c.Transform)),
		DB:          db,
	}
	svc.UserModel = model.NewUserModel(svc.SqlConn, c.Cache)
	svc.I2billAcquirerStudentModel = model.NewI2billAcquirerStudentModel(svc.SqlConn)
	svc.RdCli = svc.UserModel.CacheStorage()
	svc.Wechat = &Wechat{
		RdCli: svc.RdCli,
		c:     c,
	}
	ServiceConfig = svc.Config
	return svc
}
