package sysdictdata

import (
	"fmt"
	"net/http"
	"strings"

	"be.ems/features/sys_dict_data/model"
	sysDictDataService "be.ems/features/sys_dict_data/service"
	sysDictTypeService "be.ems/features/sys_dict_type/service"
	"be.ems/lib/core/utils/ctx"
	"be.ems/lib/core/utils/parse"
	"be.ems/lib/core/vo/result"
	"be.ems/lib/midware"
	"be.ems/lib/services"
	"be.ems/restagent/config"
)

// 字典类型对应的字典数据信息接口添加到路由
func Routers() []services.RouterItem {
	// 实例化控制层 SysDictDataApi 结构体
	var apis = &SysDictDataApi{
		sysDictDataService: sysDictDataService.NewServiceSysDictData,
		sysDictTypeService: sysDictTypeService.NewServiceSysDictType,
	}

	rs := [...]services.RouterItem{
		{
			Method:     "GET",
			Pattern:    "/dictDatas",
			Handler:    apis.List,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "GET",
			Pattern:    "/dictData/{dictCode}",
			Handler:    apis.Info,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "POST",
			Pattern:    "/dictData",
			Handler:    apis.Add,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "PUT",
			Pattern:    "/dictData",
			Handler:    apis.Edit,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "DELETE",
			Pattern:    "/dictData/{dictCodes}",
			Handler:    apis.Remove,
			Middleware: midware.Authorize(nil),
		},
		{
			Method:     "GET",
			Pattern:    "/dictData/type/{dictType}",
			Handler:    apis.DictType,
			Middleware: midware.Authorize(nil),
		},
		// 添加更多的 Router 对象...
	}

	// 生成两组前缀路由
	rsPrefix := []services.RouterItem{}
	for _, v := range rs {
		path := "/dictDataManage/{apiVersion}" + v.Pattern
		// 固定前缀
		v.Pattern = config.DefaultUriPrefix + path
		rsPrefix = append(rsPrefix, v)
		// 可配置
		v.Pattern = config.UriPrefix + path
		rsPrefix = append(rsPrefix, v)
	}
	return rsPrefix
}

// 字典类型对应的字典数据信息
//
// PATH /dictDataManage
type SysDictDataApi struct {
	// 字典数据服务
	sysDictDataService *sysDictDataService.ServiceSysDictData
	// 字典类型服务
	sysDictTypeService *sysDictTypeService.ServiceSysDictType
}

// 字典数据列表
//
// GET /list
func (s *SysDictDataApi) List(w http.ResponseWriter, r *http.Request) {
	querys := ctx.QueryMap(r)
	data := s.sysDictDataService.SelectDictDataPage(querys)
	ctx.JSON(w, 200, result.Ok(data))
}

// 字典数据详情
//
// GET /:dictCode
func (s *SysDictDataApi) Info(w http.ResponseWriter, r *http.Request) {
	dictCode := ctx.Param(r, "dictCode")
	if dictCode == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}
	data := s.sysDictDataService.SelectDictDataByCode(dictCode)
	if data.DictCode == dictCode {
		ctx.JSON(w, 200, result.OkData(data))
		return
	}
	ctx.JSON(w, 200, result.Err(nil))
}

// 字典数据新增
//
// POST /
func (s *SysDictDataApi) Add(w http.ResponseWriter, r *http.Request) {
	var body model.SysDictData
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.DictCode != "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	// 检查字典类型是否存在
	sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
	if sysDictType.DictType != body.DictType {
		ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
		return
	}

	// 检查字典标签唯一
	uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, "")
	if !uniqueDictLabel {
		msg := fmt.Sprintf("[%s] The subscript signature of this dictionary type already exists", body.DictLabel)
		ctx.JSON(w, 200, result.ErrMsg(msg))
		return
	}

	// 检查字典键值唯一
	uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, "")
	if !uniqueDictValue {
		msg := fmt.Sprintf("[%s] The label value under this dictionary type already exists", body.DictValue)
		ctx.JSON(w, 200, result.ErrMsg(msg))
		return
	}

	body.CreateBy = ctx.LoginUserToUserName(r)
	insertId := s.sysDictDataService.InsertDictData(body)
	if insertId != "" {
		ctx.JSON(w, 200, result.Ok(nil))
		return
	}
	ctx.JSON(w, 200, result.Err(nil))
}

// 字典类型修改
//
// PUT /
func (s *SysDictDataApi) Edit(w http.ResponseWriter, r *http.Request) {
	var body model.SysDictData
	err := ctx.ShouldBindJSON(r, &body)
	if err != nil || body.DictCode == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	// 检查字典类型是否存在
	sysDictType := s.sysDictTypeService.SelectDictTypeByType(body.DictType)
	if sysDictType.DictType != body.DictType {
		ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary type data!"))
		return
	}

	// 检查字典编码是否存在
	SysDictDataApi := s.sysDictDataService.SelectDictDataByCode(body.DictCode)
	if SysDictDataApi.DictCode != body.DictCode {
		ctx.JSON(w, 200, result.ErrMsg("No permission to access dictionary encoding data!"))
		return
	}

	// 检查字典标签唯一
	uniqueDictLabel := s.sysDictDataService.CheckUniqueDictLabel(body.DictType, body.DictLabel, body.DictCode)
	if !uniqueDictLabel {
		msg := fmt.Sprintf("Data modification failed for [%s], the dictionary type subscript signature already exists", body.DictLabel)
		ctx.JSON(w, 200, result.ErrMsg(msg))
		return
	}

	// 检查字典键值唯一
	uniqueDictValue := s.sysDictDataService.CheckUniqueDictValue(body.DictType, body.DictValue, body.DictCode)
	if !uniqueDictValue {
		msg := fmt.Sprintf("Data modification failed for [%s], label value already exists under this dictionary type", body.DictValue)
		ctx.JSON(w, 200, result.ErrMsg(msg))
		return
	}

	body.UpdateBy = ctx.LoginUserToUserName(r)
	rows := s.sysDictDataService.UpdateDictData(body)
	if rows > 0 {
		ctx.JSON(w, 200, result.Ok(nil))
		return
	}
	ctx.JSON(w, 200, result.Err(nil))
}

// 字典数据删除
//
// DELETE /:dictCodes
func (s *SysDictDataApi) Remove(w http.ResponseWriter, r *http.Request) {
	dictCodes := ctx.Param(r, "dictCodes")
	if dictCodes == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}
	// 处理字符转id数组后去重
	ids := strings.Split(dictCodes, ",")
	uniqueIDs := parse.RemoveDuplicates(ids)
	if len(uniqueIDs) <= 0 {
		ctx.JSON(w, 200, result.Err(nil))
		return
	}
	rows, err := s.sysDictDataService.DeleteDictDataByCodes(uniqueIDs)
	if err != nil {
		ctx.JSON(w, 200, result.ErrMsg(err.Error()))
		return
	}
	msg := fmt.Sprintf("Successfully deleted: %d", rows)
	ctx.JSON(w, 200, result.OkMsg(msg))
}

// 字典数据列表（指定字典类型）
//
// GET /type/:dictType
func (s *SysDictDataApi) DictType(w http.ResponseWriter, r *http.Request) {
	dictType := ctx.Param(r, "dictType")
	if dictType == "" {
		ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
		return
	}

	data := s.sysDictDataService.SelectDictDataByType(dictType)
	ctx.JSON(w, 200, result.OkData(data))
}
