package comm

import (
	"applet/app/db"
	"applet/app/e"
	"applet/app/enum"
	"applet/app/md"
	"applet/app/svc"
	"applet/app/svc/sys_cfg"
	"applet/app/utils"
	"applet/app/utils/cache"
	"code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
	enum2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum"
	"fmt"
	sts20150401 "github.com/alibabacloud-go/sts-20150401/v2/client"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/gin-gonic/gin"
	"strings"
)

// MenuList
// @Summary      通用请求-权限列表-菜单栏列表(获取)
// @Tags         权限列表
// @Description  菜单栏列表(获取)
// @Accept       json
// @Produce      json
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success      200   {object}    map[string]interface{}	"具体路由"
// @Failure      400   {object}   md.Response              	"具体错误"
// @Router       /api/comm/getMenuList [POST]
func MenuList(c *gin.Context) {
	engine := db.Db
	admin := svc.GetUser(c)
	qrcodeWithBatchRecordsDb := implement.NewPermissionGroupDb(engine)
	groupList, err := qrcodeWithBatchRecordsDb.FindPermissionGroup()
	if err != nil {
		e.OutErr(c, e.ERR_DB_ORM, err.Error())
		return
	}

	// 1、查询出当前用户所有角色
	adminRoleDb := implement.NewAdminRoleDb(engine)
	roles, err := adminRoleDb.FindAdminRole(admin.AdmId)
	if err != nil {
		e.OutErr(c, e.ERR_DB_ORM, err.Error())
		return
	}

	roleDb := implement.NewRoleDb(engine, 0)
	var adminHasPermissionGroupIds []string
	for _, v := range *roles {
		list, _, err1 := roleDb.FindPermissionGroupByRole(v.RoleId)
		if err1 != nil {
			e.OutErr(c, e.ERR_DB_ORM, err1.Error())
			return
		}
		for _, v1 := range list {
			adminHasPermissionGroupIds = append(adminHasPermissionGroupIds, utils.IntToStr(v1.PermissionGroup.Id))
		}
	}

	var tempRespMap = map[string]*md.PermissionGroupListResp{}
	var tempRespMapKeys []string
	for _, v := range *groupList {

		var isCheck bool
		if admin.IsSuperAdministrator == enum.IsSuperAdministratorTure {
			isCheck = true
		} else {
			isCheck = false
		}

		if utils.InArr(utils.IntToStr(v.Id), adminHasPermissionGroupIds) {
			isCheck = true
		}

		if v.State == enum.PermissionGroupStateForDiscard {
			isCheck = false
		}

		tempRespMap[utils.IntToStr(v.Id)] = &md.PermissionGroupListResp{
			Id:       v.Id,
			Name:     v.Name,
			Key:      v.Key,
			State:    v.State,
			ParentId: v.ParentId,
			CreateAt: v.CreateAt,
			UpdateAt: v.UpdateAt,
			IsCheck:  isCheck,
		}
		tempRespMapKeys = append(tempRespMapKeys, utils.IntToStr(v.Id))
	}
	for _, v := range tempRespMap {
		if v.ParentId != 0 && tempRespMap[utils.IntToStr(v.ParentId)].ParentId != 0 {
			tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList = append(tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList, *v)
		}
	}
	for _, v := range tempRespMap {
		if v.ParentId != 0 && tempRespMap[utils.IntToStr(v.ParentId)].ParentId == 0 {
			tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList = append(tempRespMap[utils.IntToStr(v.ParentId)].SubPermissionGroupList, *v)
		}
	}

	var resp []*md.PermissionGroupListResp
	for _, v := range tempRespMapKeys {
		if tempRespMap[v].ParentId == 0 {
			resp = append(resp, tempRespMap[v])
		}
	}

	e.OutSuc(c, map[string]interface{}{
		"list": resp,
		"state": []map[string]interface{}{
			{
				"name":  enum.PermissionGroupState(enum.PermissionGroupStateForNormal).String(),
				"value": enum.PermissionGroupStateForNormal,
			},
			{
				"name":  enum.PermissionGroupState(enum.PermissionGroupStateForDiscard).String(),
				"value": enum.PermissionGroupStateForDiscard,
			},
		},
	}, nil)
	return
}

type ImgReqUploadReq struct {
	FileName    string `json:"file_name" binding:"required" example:"文件名"`
	ContentType string `json:"content_type,required" binding:"required" example:"image/jpeg"`
}
type ImgReqUploadResp struct {
	SignUrl string `json:"sign_url" example:"签名上传url"`
}

// GetOssUrl
// @Summary      通用请求-对象存储-上传许可链接(获取)
// @Tags         对象存储
// @Description  上传许可链接(获取)
// @Accept       json
// @Produce      json
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Param    req    body	comm.ImgReqUploadReq 	true  "签名上传url"
// @Success      200   {string}  	"许可链接"
// @Failure      400   {object}   md.Response              	"具体错误"
// @Router       /api/comm/getOssUrl [POST]
func GetOssUrl(c *gin.Context) {
	var args ImgReqUploadReq
	err := c.ShouldBindJSON(&args)
	if err != nil {
		err = svc.HandleValidateErr(err)
		err1 := err.(e.E)
		e.OutErr(c, err1.Code, err1.Error())
		return
	}
	CommOss(c, args)
}
func CommOss(c *gin.Context, args ImgReqUploadReq) {
	sysCfgDb := sys_cfg.NewSysCfgDb(db.Db)
	sysCfgs, err := sysCfgDb.SysCfgGetAll()
	if err != nil {
		e.OutErr(c, e.ERR_DB_ORM, err.Error())
		return
	}
	if sysCfgs == nil {
		e.OutErr(c, e.ERR_CFG_CACHE, nil)
		return
	}

	cfgMap := make(map[string]string, len(*sysCfgs))
	for _, cfg := range *sysCfgs {
		cfgMap[cfg.Key] = cfg.Val
	}
	endpoint := cfgMap[enum2.AliyunOssEndpoint]
	bucketName := cfgMap[enum2.AliyunOssBucketName]
	ossBucketScheme := cfgMap[enum2.AliyunOssBucketScheme]
	accessKeyID := cfgMap[enum2.AliyunOssAccessKeyID]
	accessKeySecret := cfgMap[enum2.AliyunOssAccessKeySecret]

	// 创建OSSClient实例。
	client, err := oss.New(ossBucketScheme+"://"+endpoint, accessKeyID, accessKeySecret)
	if err != nil {
		e.OutErr(c, e.ERR, err.Error())
		return
	}

	// 获取存储空间。
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		e.OutErr(c, e.ERR, err.Error())
		return
	}

	options := []oss.Option{
		oss.ContentType(args.ContentType),
	}

	signedURL, err := bucket.SignURL(args.FileName, oss.HTTPPut, 60*5, options...)
	if err != nil {
		e.OutErr(c, e.ERR_AES_ENCODE, err.Error())
		return
	}

	e.OutSuc(c, signedURL, nil)
}

const STSVoucherRedisKey = "STS_Voucher_Cache_Key"

type GetSTSVoucherResp struct {
	STSToken sts20150401.AssumeRoleResponseBodyCredentials `json:"sts_token"` // STS 凭证
	Bucket   string                                        `json:"bucket"`    // oss 桶名称
	Region   string                                        `json:"region"`    // 所在地域
}

// GetSTSVoucher
// @Summary      通用请求-打包机使用-STS临时访问凭证(获取)
// @Tags         打包机使用
// @Description  STS临时访问凭证(获取)
// @Accept       json
// @Produce      json
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success      200   {object}  comm.GetSTSVoucherResp  "凭证及其他信息"
// @Failure      400   {object}   md.Response              	"具体错误"
// @Router       /api/getSTSVoucher [GET]
func GetSTSVoucher(c *gin.Context) {
	sysCfgDb := sys_cfg.NewSysCfgDb(db.Db)
	sysCfgs, err := sysCfgDb.SysCfgGetAll()
	if err != nil {
		e.OutErr(c, e.ERR_DB_ORM, err.Error())
		return
	}
	if sysCfgs == nil {
		e.OutErr(c, e.ERR_CFG_CACHE, nil)
		return
	}
	cfgMap := make(map[string]string, len(*sysCfgs))
	for _, cfg := range *sysCfgs {
		cfgMap[cfg.Key] = cfg.Val
	}
	endpoint := cfgMap[enum2.AliyunOssEndpoint]

	redisKey := STSVoucherRedisKey
	redisValue, err := cache.GetString(redisKey)
	if err != nil {
		if err.Error() == "redigo: nil returned" {

			assumeRoleAccessKeyID := cfgMap[enum2.AliyunOssAssumeRoleAccessKeyID]
			assumeRoleAccessKeySecret := cfgMap[enum2.AliyunOssAssumeRoleAccessKeySecret]
			assumeRoleARN := cfgMap[enum2.AliyunOssAssumeRoleARN]
			roleSessionName := "STSRam"

			endpointList := strings.Split(endpoint, "-")
			stsEndPoint := fmt.Sprintf("sts.%s-%s", endpointList[1], endpointList[2])

			client, err := svc.CreateSTSClient(&assumeRoleAccessKeyID, &assumeRoleAccessKeySecret, &stsEndPoint)
			if err != nil {
				e.OutErr(c, e.ERR, err.Error())
				return
			}

			roleArn := assumeRoleARN
			durationSeconds := 3600

			assumeRoleResponse, err := svc.AssumeRole(client, &roleArn, &roleSessionName, int64(durationSeconds))
			if err != nil {
				e.OutErr(c, e.ERR, err.Error())
				return
			}

			CredentialsStr := utils.SerializeStr(assumeRoleResponse.Body.Credentials)
			// 提早 60s 释放,避免能拿到令牌但无法上传
			cache.SetEx(redisKey, CredentialsStr, durationSeconds-60)
			credentials := sts20150401.AssumeRoleResponseBodyCredentials{
				AccessKeyId:     assumeRoleResponse.Body.Credentials.AccessKeyId,
				AccessKeySecret: assumeRoleResponse.Body.Credentials.AccessKeySecret,
				Expiration:      assumeRoleResponse.Body.Credentials.Expiration,
				SecurityToken:   assumeRoleResponse.Body.Credentials.SecurityToken,
			}

			bucket := cfgMap[enum2.AliyunOssBucketName]
			region := strings.Split(endpoint, ".")[0]

			resp := GetSTSVoucherResp{
				STSToken: credentials,
				Bucket:   bucket,
				Region:   region,
			}
			e.OutSuc(c, resp, nil)
			return
		} else {
			e.OutErr(c, e.ERR, nil)
			return
		}
	}

	var credentials sts20150401.AssumeRoleResponseBodyCredentials
	utils.Unserialize([]byte(redisValue), &credentials)
	bucket := cfgMap[enum2.AliyunOssBucketName]
	region := strings.Split(endpoint, ".")[0]

	resp := GetSTSVoucherResp{
		STSToken: credentials,
		Bucket:   bucket,
		Region:   region,
	}
	e.OutSuc(c, resp, nil)
	return

}

type GetAdminInfoResp struct {
	AdmId                int    `json:"adm_id"`                 // 管理员id
	Username             string `json:"username"`               // 用户名
	State                int    `json:"state"`                  // 状态(1:正常 2:冻结)
	IsSuperAdministrator int    `json:"is_super_administrator"` // 是否为超级管理员(0:否 1:是)
	Memo                 string `json:"memo"`                   // 备注信息
}

// GetAdminInfo
// @Summary      通用请求-获取管理员信息
// @Tags         通用请求
// @Description  获取管理员信息
// @Accept       json
// @Produce      json
// @param Authorization header string true "验证参数Bearer和token空格拼接"
// @Success      200   {object}  GetAdminInfoResp  	"管理员信息"
// @Failure      400   {object}   md.Response              	"具体错误"
// @Router       /api/comm/adminInfo [POST]
func GetAdminInfo(c *gin.Context) {
	admin := svc.GetUser(c)
	resp := GetAdminInfoResp{
		AdmId:                admin.AdmId,
		Username:             admin.Username,
		State:                admin.State,
		IsSuperAdministrator: admin.IsSuperAdministrator,
		Memo:                 admin.Memo,
	}
	e.OutSuc(c, resp, nil)
}