package ii

import (
	"encoding/json"
	"fmt"
	"net/http"

	"git.simanc.com/software/golib/v4/gio"
)

const (
	maxReadFromValidateSize = 4096
)

// Request: {"itemName": "test.test", "fieldName": ["testFloat64", "testInt64"]}
// Response: {"itemName: "test.test", "fields": [...]}
// Response.field: {
//              "name":"testFloat64",
//              "label": "测试Float"
//              "type":"float64",
//              "required":true,
//              "unique":false,
//              "minimum":1,
//              "maximum":3.1415,
//              "decimal":3,
//              "default": 3.1415
//              "enums": [{"key":"3.1415","value":3.1415}]
//          }

// type formValidateGet struct {
// 	ItemName  string   `json:"itemName"`
// 	FieldName []string `json:"fieldName"`
// }
//
// type formValidateGetResponse struct {
// 	ItemName string          `json:"itemName"`
// 	Fields   []FieldInfoJSON `json:"fields"`
// }
//
// type formValidationHandler struct {
// 	items Items
// }
//
// func (f *formValidationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 	b, err := network.HTTP.ReadRequestBody(w, r, maxReadFromValidateSize)
// 	if err != nil {
// 		network.HTTP.Error(w, http.StatusBadRequest)
// 		return
// 	}
// 	var fvg formValidateGet
// 	if err = json.Unmarshal(b, &fvg); err != nil {
// 		network.HTTP.Error(w, http.StatusBadRequest)
// 		return
// 	}
// 	itemInfo, ok := f.items.Has(fvg.ItemName)
// 	if !ok {
// 		network.HTTP.Error(w, http.StatusNotFound)
// 		return
// 	}
//
// 	formResp := new(formValidateGetResponse)
// 	formResp.ItemName = fvg.ItemName
// 	formResp.Fields = make([]FieldInfoJSON, len(fvg.FieldName))
//
// 	for i, fieldName := range fvg.FieldName {
// 		field, o := itemInfo.Field(fieldName)
// 		if !o {
// 			network.HTTP.Error(w, http.StatusBadRequest)
// 			return
// 		}
// 		formResp.Fields[i] = field.ValidateJSON()
// 	}
//
// 	p, err := json.Marshal(formResp)
// 	if err != nil {
// 		network.HTTP.Error(w, http.StatusInternalServerError)
// 		return
// 	}
//
// 	w.Header().Set("Content-Type", network.HTTPContentTypeJson)
// 	w.WriteHeader(http.StatusOK)
// 	_, _ = w.Write(p)
// }
//
// func NewFormValidateHandle(items Items) http.Handler {
// 	fvh := formValidationHandler{
// 		items: items,
// 	}
// 	return &fvh
// }

func NewFormHandler(items Items) http.Handler {
	return &formLowCode{items: items}
}

type FormLowCodeRequest struct {
	ItemName Name     `json:"itemName"`
	Fields   []string `json:"fields"`
}

type formLowCode struct {
	items Items
}

// Request: {"itemName":"test.test", "fields": ["name1","name2"]}
// Response: {"itemName":"test.test","fields": ["htmlCode","htmlCode"]}
func (l *formLowCode) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	b, err := gio.ReadLimit(r.Body, maxReadFromValidateSize)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var flc FormLowCodeRequest
	if err = json.Unmarshal(b, &flc); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	itemInfo, ok := l.items.Has(flc.ItemName)
	if !ok {
		http.Error(w, "item not found: "+flc.ItemName.String(), http.StatusNotFound)
		return
	}
	codeStr := make([]string, len(flc.Fields))
	for i, fieldName := range flc.Fields {
		field, o := itemInfo.Field(fieldName)
		if !o {
			http.Error(w, fmt.Sprintf("field not found: %s.%s", flc.ItemName, fieldName), http.StatusNotFound)
			return
		}
		if field.Form.Mode == "" {
			continue
		}
		codeStr[i] = field.Former()
	}
	p, err := json.Marshal(FormLowCodeRequest{ItemName: flc.ItemName, Fields: codeStr})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	_, _ = w.Write(p)
}
