package v1

import (
	"crypto/rand"
	"designs/app/common/request"
	"designs/app/common/response"
	"designs/global"
	"designs/model"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"math/big"
	"time"
)

func AdminList(c *gin.Context) {
	form := request.Check(c, &struct {
		Offset int    `form:"offset" binding:""`
		Limit  int    `form:"limit" binding:""`
		Search string `form:"search" binding:""`
	}{})

	query := global.App.DB.Table("admin")

	if form.Search != "" {
		query = query.WhereRaw("account LIKE ?", "%"+form.Search+"%")
	}

	var admin []model.Admin

	type adminRes struct {
		ID         int         `json:"id" gorm:"not null;"`
		Account    string      `json:"account" gorm:"not null;"`
		Name       string      `json:"name" gorm:"not null;"`
		CreatedAt  model.XTime `json:"createdAt" gorm:"column:createdAt;"`
		UpdatedAt  model.XTime `json:"updatedAt" gorm:"column:updatedAt;"`
		Permission interface{} `json:"permission" gorm:""`
	}

	var count int64
	err := query.Count(&count).Error
	if err != nil {
		response.Fail(c, 501, err.Error())
		return
	}

	err = query.Offset(form.Offset).Select("id", "account", "name", "createdAt", "updatedAt", "permission").Limit(form.Limit).Scan(&admin).Error
	if err != nil {
		response.Fail(c, 501, err.Error())
		return
	}

	var res []adminRes

	for _, v := range admin {
		var PermissionSlice []string

		json.Unmarshal([]byte(v.Permission), &PermissionSlice)

		res = append(res, adminRes{
			ID:         v.ID,
			Account:    v.Account,
			Name:       v.Name,
			CreatedAt:  v.CreatedAt,
			UpdatedAt:  v.UpdatedAt,
			Permission: PermissionSlice,
		})
	}

	response.Success(c, gin.H{"data": res, "count": count})
}

func RandomString(length int) (string, error) {
	const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, length)
	for i := range b {
		n, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
		if err != nil {
			return "", err
		}
		b[i] = charset[n.Int64()]
	}
	return string(b), nil
}

func SetAdmin(c *gin.Context) {
	form := request.Check(c, &struct {
		Account string `form:"account" binding:"required"`
		Name    string `form:"name" binding:"required"`
		//Password   string   `form:"password" binding:"required"`
		Permission []string `form:"permission" binding:"required"`
	}{})

	var admin model.Admin
	global.App.DB.WhereRaw("account = ?", form.Account).First(&admin)
	if admin.ID != 0 {
		response.Fail(c, 1001, "账户名称重复")
		return
	}

	password, _ := RandomString(10)

	now := model.XTime{Time: time.Now()}
	admin.Account = form.Account
	admin.Password = password
	admin.Name = form.Name
	admin.CreatedAt = now
	admin.UpdatedAt = now
	p, _ := json.Marshal(form.Permission)
	admin.Permission = string(p)

	err := global.App.DB.Table("admin").Create(&admin).Error
	if err != nil {
		response.Fail(c, 502, err.Error())
		return
	}

	response.Success(c, gin.H{
		"data": map[string]interface{}{
			"password": password,
		},
	})
}

func DeleteAdmin(c *gin.Context) {
	form := request.Check(c, &struct {
		AdminId int `form:"adminId" binding:"required"`
	}{})

	if form.AdminId == 1 {
		response.Fail(c, 501, "默认管理员无法删除")
		return
	}
	var d interface{}
	err := global.App.DB.Table("admin").Where("id", form.AdminId).Delete(d).Error
	if err != nil {
		response.Fail(c, 502, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

func UpdateAdmin(c *gin.Context) {
	form := request.Check(c, &struct {
		AdminId    int      `form:"adminId" binding:"required"`
		Name       string   `form:"name" binding:"required"`
		Permission []string `form:"permission" binding:""`
		Password   string   `form:"password" binding:""`
	}{})

	update := make(map[string]interface{})

	if form.AdminId == 1 {
		response.Fail(c, 501, "默认管理员无法编辑")
		return
	}

	if form.Permission != nil {
		p, _ := json.Marshal(form.Permission)
		update["permission"] = string(p)
	}
	if form.Password != "" {
		update["password"] = form.Password
	}
	if form.Name != "" {
		update["name"] = form.Name
	}

	if len(form.Permission) == 0 {
		response.Fail(c, 501, "没有更新")
		return
	}
	update["updatedAt"] = time.Now()

	err := global.App.DB.Table("admin").Where("id", form.AdminId).Updates(update).Error
	if err != nil {
		response.Fail(c, 502, "更新失败"+err.Error())
		return
	}

	response.Success(c, gin.H{})
}
