package results

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"

	"github.com/go-chi/render"
	"github.com/librespeed/speedtest-go/config"
	"github.com/librespeed/speedtest-go/database"
	log "github.com/sirupsen/logrus"
)

// formatValue formats a numeric string for display, matching PHP behavior:
//   - values < 10: 2 decimal places
//   - values < 100: 1 decimal place
//   - values >= 100: 0 decimal places
func formatValue(d string) string {
	val, err := strconv.ParseFloat(d, 64)
	if err != nil {
		return d
	}
	if val < 10 {
		return strconv.FormatFloat(val, 'f', 2, 64)
	}
	if val < 100 {
		return strconv.FormatFloat(val, 'f', 1, 64)
	}
	return strconv.FormatFloat(val, 'f', 0, 64)
}

// extractISPName extracts the ISP name from the processedString format:
// "IP - ISP, Country (distance)" → "ISP"
func extractISPName(processedString string) string {
	dash := strings.Index(processedString, "-")
	if dash == -1 {
		return ""
	}
	isp := strings.TrimSpace(processedString[dash+1:])
	par := strings.LastIndex(isp, "(")
	if par != -1 {
		isp = strings.TrimSpace(isp[:par])
	}
	return isp
}

// JSONResponse is the structure returned by the JSON results endpoint
type JSONResponse struct {
	Timestamp string `json:"timestamp"`
	Download  string `json:"download"`
	Upload    string `json:"upload"`
	Ping      string `json:"ping"`
	Jitter    string `json:"jitter"`
	ISPInfo   string `json:"ispinfo"`
}

// JSONResult handles GET /results/json?id=X and returns test results as JSON
func JSONResult(w http.ResponseWriter, r *http.Request) {
	conf := config.LoadedConfig()

	if conf.DatabaseType == "none" {
		render.PlainText(w, r, "Telemetry is disabled")
		return
	}

	rawID := r.FormValue("id")
	if rawID == "" {
		w.WriteHeader(http.StatusBadRequest)
		render.JSON(w, r, map[string]string{"error": "missing id parameter"})
		return
	}

	uuid := ResolveID(rawID)
	record, err := database.DB.FetchByUUID(uuid)
	if err != nil {
		log.Errorf("Error querying database for JSON result: %s", err)
		w.WriteHeader(http.StatusNotFound)
		render.JSON(w, r, map[string]string{"error": "result not found"})
		return
	}

	// Format values for display (matching PHP json.php behavior)
	resp := JSONResponse{
		Timestamp: record.Timestamp.Format("2006-01-02 15:04:05"),
		Download:  formatValue(record.Download),
		Upload:    formatValue(record.Upload),
		Ping:      formatValue(record.Ping),
		Jitter:    formatValue(record.Jitter),
	}

	// Extract ISP name from ISP info JSON
	var result Result
	if err := json.Unmarshal([]byte(record.ISPInfo), &result); err == nil {
		resp.ISPInfo = extractISPName(result.ProcessedString)
	}

	w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, s-maxage=0")
	w.Header().Add("Cache-Control", "post-check=0, pre-check=0")
	w.Header().Set("Pragma", "no-cache")
	render.JSON(w, r, resp)
}
