package service

import (
	"context"
	"encoding/json"
	"errors"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility/serializer"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
	"gorm.io/gorm"
	"time"
)

// AdminRole 后台角色
var AdminRole = new(sAdminRole)

type sAdminRole struct{}

func (s *sAdminRole) List(ctx *gin.Context, req forms.AdminRoleListReq) serializer.Response {
	var (
		q            = query.Use(config.AdminDB).AdminRole
		m            = q.WithContext(ctx)
		mq           = query.Use(config.DB).AdminRoleMenu
		mm           = mq.WithContext(context.Background())
		offset int64 = 0
		models forms.UserAccountListRes
		lists  []*forms.AdminRoleListModel
	)

	m = m.Order(q.Sort).Order(q.ID.Desc())

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}
	}

	for _, v := range lists {
		err = json.Unmarshal([]byte(cast.ToString(v.Permissions)), &v.Permissions)
		pages := make([]int64, 0)
		if err := mm.Where(mq.RoleID.Eq(int32(v.ID))).Pluck(mq.PageID, &pages); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 pages", err)
		}
		v.Pages = pages
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

func (s *sAdminRole) Edit(ctx *gin.Context, req forms.AdminRoleEditReq) serializer.Response {
	q := query.Use(config.AdminDB).AdminRole
	mq := query.Use(config.DB).AdminRoleMenu
	m := mq.WithContext(context.Background())

	logrus.Warnf("req:%+v", req)

	marshal, err := json.Marshal(req.Permissions)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "Marshal err", err)
	}
	menusModel := make([]*model.AdminRoleMenu, 0)
	for _, menu := range req.Pages {
		menusModel = append(menusModel, &model.AdminRoleMenu{
			RoleID: int32(req.ID),
			PageID: int32(menu),
		})
	}

	// 修改
	if req.ID > 0 {
		update := &model.AdminRole{
			Name:        req.Name,
			Key:         req.Key,
			Sort:        req.Sort,
			Permissions: string(marshal),
			Remark:      req.Remark,
			Status:      req.Status,
			UpdatedAt:   time.Now(),
		}
		_, err := q.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(update)
		if err != nil {
			return serializer.Err(consts.CodeParamErr, "更新出错", err)
		}
		// 删除旧的菜单权限
		if _, err := m.Where(mq.RoleID.Eq(int32(req.ID))).Delete(); err != nil {
			return serializer.Response{}
		}
		// 插入新的菜单权限
		if err := m.Create(menusModel...); err != nil {
			return serializer.Response{}
		}
		return serializer.Suc(nil)
	}

	// 新增
	create := &model.AdminRole{
		Name:        req.Name,
		Key:         req.Key,
		Sort:        req.Sort,
		Permissions: string(marshal),
		Remark:      req.Remark,
		Status:      req.Status,
		UpdatedAt:   time.Now(),
		CreatedAt:   time.Now(),
	}
	if err := query.Use(config.AdminDB).AdminRole.WithContext(ctx).Create(create); err != nil {
		logrus.Error(err)
		return serializer.DBErr(err.Error(), err)
	}
	// 插入新的菜单权限
	for _, item := range menusModel {
		item.RoleID = int32(create.ID)
	}
	if err := m.Create(menusModel...); err != nil {
		logrus.Error(err)
		return serializer.DBErr(err.Error(), err)
	}

	return serializer.Suc(nil)
}

func (s *sAdminRole) GetRole(ctx *gin.Context, req forms.AdminRoleReq) (*model.AdminRole, error) {
	var (
		q = query.Use(config.AdminDB).AdminRole
		m = q.WithContext(ctx)
	)
	result, err := m.Where(q.ID.Eq(req.ID)).First()
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		return nil, err
	}
	return result, nil
}
