package response

import (
	"fmt"
	"github.com/exhibition-main/internal/model"
	"github.com/exhibition-main/internal/msg"
	"github.com/gin-gonic/gin"
	"net/http"
	"reflect"
)

func ResponseMsg(c *gin.Context, httpCode int, Resp model.Response) {
	if httpCode == 0 {
		httpCode = http.StatusOK
	}
	c.JSON(httpCode, model.Response{
		Status: Resp.Status,
		Msg:    Resp.Msg,
		Data:   Resp.Data,
	})
}

func ResponseQuickMsg(c *gin.Context, Status uint8, Msg string, Data interface{}) {
	//var c gin.Context
	c.JSON(http.StatusOK, model.Response{
		Status: int(Status),
		Msg:    Msg,
		Data:   Data,
	})
}

func Success(c *gin.Context, datas ...interface{}) {
	var data any
	if datas != nil {
		data = datas[0]
	}
	dataFieldStr, _ := c.Get("dataField")
	key := []string{"*"}

	if dataFieldStr != "" && dataFieldStr != nil {
		dataField := dataFieldStr.([]string)
		key = dataField

		if len(dataField) == 1 && dataField[0] == "*" { //不做处理

		} else if len(dataField) >= 1 {
			isList := isList(reflect.TypeOf(data).Elem())

			// 是列表返回
			if isList == false {
				ChangeFromReflect(data, dataField)
			} else {
				ChangeRawFromReflect(data, dataField)
			}
		}
	}

	c.JSON(http.StatusOK, model.Response{
		Status: msg.Ok,
		Code:   msg.StatusOK,
		Data:   data,
		//	Keys:   dataField,
		Keys: key,
	})
	c.Abort()
}

func IsContainString(items []string, item string) bool {
	for _, eachItem := range items {
		if eachItem == item {
			return true
		}
	}
	return false
}

func ChangeFromReflect(data interface{}, dataField []string) {
	m := reflect.TypeOf(data).Elem()
	for i := 0; i < m.NumField(); i++ {
		fieldType := m.Field(i)
		if IsContainString(dataField, fieldType.Name) == false {
			field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)

			switch m.Field(i).Type.Name() {
			case "int":
				if field.CanSet() {
					field.SetInt(0)
				}
			case "uint":
				if field.CanSet() {
					field.SetUint(0)
				}
			case "uint64":
				if field.CanSet() {
					field.SetUint(0)
				}
			case "string":
				if field.CanSet() {
					field.SetString("")
				}
			default:
				if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).CanAddr() {
					if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Slice {
						field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)

						if field.CanSet() {
							field.Set(reflect.MakeSlice(field.Type(), 0, 0))
						}
					}

					if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Struct {
					}

					if reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Kind() == reflect.Ptr {
						field := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name)
						if !reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).IsNil() {
							fieldType := reflect.ValueOf(data).Elem().FieldByName(fieldType.Name).Elem().Type()

							if field.CanSet() {
								field.Set(reflect.New(fieldType))
							}
						}

					}
				}

			}
		}
	}

}

func ChangeRawFromReflect(data interface{}, dataField []string) {

	sliceContent := reflect.ValueOf(data).Elem().FieldByName("Data")
	for i := 0; i < sliceContent.Len(); i++ {
		sliceContent.Index(i)
		ChangeFromReflect(sliceContent.Index(i).Interface(), dataField)
	}

}

func isList(m reflect.Type) bool {
	dataExist := false

	for i := 0; i < m.NumField(); i++ {

		fieldType := m.Field(i)

		if fieldType.Name == "Data" {
			getValue := reflect.ValueOf(fieldType)

			if getValue.Kind() != reflect.Slice {
				dataExist = true
			}

			break
		}
	}

	return dataExist
}

// Error 统一错误返回
func Error(c *gin.Context, code int, err error, message ...string) {

	fmt.Println("err:", err)
	status := msg.Fail
	if code == msg.StatusUnauthorized {
		status = msg.StatusUnauthorized
	}
	var msgStr string
	if message != nil {
		msgStr = message[0]
	} else if err != nil {
		msgStr = err.Error()
	}
	c.JSON(msg.StatusOK, model.Response{
		Status: status,
		Msg:    msgStr,
		Data:   nil,
	})

	c.Abort()
}