package ginext

import (
	"github.com/gin-gonic/gin"
	json "gogs.mikescher.com/BlackForestBytes/goext/gojson"
	"gogs.mikescher.com/BlackForestBytes/goext/langext"
)

type jsonHTTPResponse struct {
	statusCode     int
	data           any
	headers        []headerval
	cookies        []cookieval
	filterOverride *string
}

func (j jsonHTTPResponse) jsonRenderer(g *gin.Context) json.GoJsonRender {
	var f *string
	if jsonfilter := g.GetString(jsonFilterKey); jsonfilter != "" {
		f = &jsonfilter
	}
	if j.filterOverride != nil {
		f = j.filterOverride
	}
	return json.GoJsonRender{Data: j.data, NilSafeSlices: true, NilSafeMaps: true, Filter: f}
}

func (j jsonHTTPResponse) Write(g *gin.Context) {
	for _, v := range j.headers {
		g.Header(v.Key, v.Val)
	}
	for _, v := range j.cookies {
		g.SetCookie(v.name, v.value, v.maxAge, v.path, v.domain, v.secure, v.httpOnly)
	}
	g.Render(j.statusCode, j.jsonRenderer(g))
}

func (j jsonHTTPResponse) WithHeader(k string, v string) HTTPResponse {
	j.headers = append(j.headers, headerval{k, v})
	return j
}

func (j jsonHTTPResponse) WithCookie(name string, value string, maxAge int, path string, domain string, secure bool, httpOnly bool) HTTPResponse {
	j.cookies = append(j.cookies, cookieval{name, value, maxAge, path, domain, secure, httpOnly})
	return j
}

func (j jsonHTTPResponse) IsSuccess() bool {
	return j.statusCode >= 200 && j.statusCode <= 399
}

func (j jsonHTTPResponse) Statuscode() int {
	return j.statusCode
}

func (j jsonHTTPResponse) BodyString(g *gin.Context) *string {
	if str, err := j.jsonRenderer(g).RenderString(); err == nil {
		return &str
	} else {
		return nil
	}
}

func (j jsonHTTPResponse) ContentType() string {
	return "application/json"
}

func (j jsonHTTPResponse) Headers() []string {
	return langext.ArrMap(j.headers, func(v headerval) string { return v.Key + "=" + v.Val })
}

func JSON(sc int, data any) HTTPResponse {
	return &jsonHTTPResponse{statusCode: sc, data: data}
}

func JSONWithFilter(sc int, data any, f string) HTTPResponse {
	return &jsonHTTPResponse{statusCode: sc, data: data, filterOverride: &f}
}