package api

import (
	"net"
	"net/http"
	"time"

	error2 "github.com/pingcap-inc/clinic/pkg/error"
)

type JSONResponseWriter interface {
	JSON(code int, obj any)
}

type JSONWriterFunc func(code int, obj any)

func (j JSONWriterFunc) JSON(code int, obj any) {
	j(code, obj)
}

type Status struct {
	Code    int64  `json:"code"`
	Message string `json:"message"`
}

func SendMsgWithoutReturn(writer JSONResponseWriter, err *error2.ClinicErr) {
	if err == nil {
		writer.JSON(http.StatusOK, BaseResponse{Status: "OK"})
		return
	}

	SendErrorMessage(writer, err)
}

func SendMessageWithReturn(writer JSONResponseWriter, err *error2.ClinicErr, resp any) {
	if err == nil {
		writer.JSON(http.StatusOK, resp)
		return
	}

	SendErrorMessage(writer, err)
}

func SendErrorMessage(writer JSONResponseWriter, err *error2.ClinicErr) {
	if err.IsNotFound() {
		writer.JSON(http.StatusNotFound, &Status{Code: err.Code(), Message: err.Error()})
		return
	}

	if err.IsRequestErr() {
		writer.JSON(http.StatusBadRequest, &Status{Code: err.Code(), Message: err.Error()})
		return
	}

	if err.IsInternalErr() {
		writer.JSON(http.StatusInternalServerError, &Status{Code: err.Code(), Message: err.Error()})
		return
	}

	if err.IsProcessingErr() {
		writer.JSON(http.StatusProcessing, &Status{Code: err.Code(), Message: err.Error()})
		return
	}

	writer.JSON(http.StatusServiceUnavailable, &Status{Code: err.Code(), Message: "Service Unavailable"})
}

//func SendBadRequestMsg(writer JSONResponseWriter, code int64, msg string) {
//	writer.JSON(http.StatusBadRequest, &Status{Code: code, Message: msg})
//}
//
//func SendServerErrMsg(writer JSONResponseWriter, code int64, msg string) {
//	writer.JSON(http.StatusServiceUnavailable, &Status{Code: code, Message: msg})
//}
//
//func SendSuccess(writer JSONResponseWriter, respData interface{}) {
//	writer.JSON(http.StatusOK, respData)
//}

func CustomizedTransport() http.RoundTripper {
	defaultTransPtr, ok := http.DefaultTransport.(*http.Transport)
	if !ok {
		return http.DefaultTransport
	}
	return &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		DialContext: (&net.Dialer{
			Timeout:   3 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
		MaxIdleConns: 100,
		// increase the conn count for better concurrency
		MaxIdleConnsPerHost:   10,
		ResponseHeaderTimeout: 30 * time.Second,
		IdleConnTimeout:       defaultTransPtr.IdleConnTimeout,
		TLSHandshakeTimeout:   defaultTransPtr.TLSHandshakeTimeout,
		ExpectContinueTimeout: defaultTransPtr.ExpectContinueTimeout,
	}
}
