package v1

import (
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"github.com/armosec/kubescape/v2/core/cautils"
	"github.com/armosec/kubescape/v2/core/cautils/logger"
	"github.com/armosec/kubescape/v2/core/cautils/logger/helpers"
	utilsapisv1 "github.com/armosec/opa-utils/httpserver/apis/v1"
	"github.com/google/uuid"
)

// Metrics http listener for prometheus support
func (handler *HTTPHandler) Metrics(w http.ResponseWriter, r *http.Request) {

	scanID := uuid.NewString()
	handler.state.setBusy(scanID)
	defer handler.state.setNotBusy(scanID)

	resultsFile := filepath.Join(OutputDir, scanID)
	scanInfo := getPrometheusDefaultScanCommand(scanID, resultsFile)

	scanParams := &scanRequestParams{
		scanQueryParams: &ScanQueryParams{
			ReturnResults: true,
			KeepResults:   false,
		},
		scanInfo: scanInfo,
		scanID:   scanID,
	}

	handler.scanResponseChan.set(scanID) // add scan to channel
	defer handler.scanResponseChan.delete(scanID)

	// send to scan queue
	logger.L().Info("requesting scan", helpers.String("scanID", scanID), helpers.String("api", "v1/metrics"))
	handler.scanRequestChan <- scanParams

	// wait for scan to complete
	results := <-handler.scanResponseChan.get(scanID)
	defer removeResultsFile(scanID) // remove json format results file
	defer os.Remove(resultsFile)    // remove prometheus format results file

	// handle response
	if results.Type == utilsapisv1.ErrorScanResponseType {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write(responseToBytes(results))
		return
	}

	// read prometheus format results file
	f, err := os.ReadFile(resultsFile)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		results.Type = utilsapisv1.ErrorScanResponseType
		results.Response = fmt.Sprintf("failed read results from file. reason: %s", err.Error())
		w.Write(responseToBytes(results))
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write(f)
}

func getPrometheusDefaultScanCommand(scanID, resultsFile string) *cautils.ScanInfo {
	scanInfo := defaultScanInfo()
	scanInfo.Submit = false // do not submit results every scan
	scanInfo.Local = true   // do not submit results every scan
	scanInfo.FrameworkScan = true
	scanInfo.ScanAll = true                                                        // scan all frameworks
	scanInfo.ScanID = scanID                                                       // scan ID
	scanInfo.FailThreshold = 100                                                   // Do not fail scanning
	scanInfo.Output = resultsFile                                                  // results output
	scanInfo.Format = envToString("KS_FORMAT", "prometheus")                       // default output should be json
	scanInfo.HostSensorEnabled.SetBool(envToBool("KS_ENABLE_HOST_SCANNER", false)) // enable host scanner
	return scanInfo
}
