/*
Copyright © 2025 cavaliba.com
*/
package poller

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/spf13/viper"
)

// JobResponse represents the response sent to Cavaliba API
type JobResponse struct {
	Results []CheckResult `json:"results"`
}

// SendResponse sends the JobResponse to Cavaliba API
func SendResponse(response JobResponse) error {
	verbose := viper.GetBool("verbose")
	method := http.MethodPost
	url := viper.GetString("url") + "appstatus/worklist/"
	sslSkipVerify := viper.GetBool("ssl_skipverify")
	timeout := time.Duration(viper.GetInt("timeout")) * time.Millisecond

	transport := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: sslSkipVerify},
	}

	httpClient := &http.Client{
		Transport: transport,
		Timeout:   timeout,
	}

	// Marshal JobResponse to JSON
	jsonData, err := json.Marshal(response)
	if err != nil {
		return fmt.Errorf("failed to marshal response: %w", err)
	}

	if verbose {
		fmt.Println("")
		fmt.Println("Sending Response to API")
		fmt.Println("=======================")
		fmt.Printf("URL:          %s\n", url)
		fmt.Printf("Method:       %s\n", method)
		fmt.Printf("JSON Payload:\n")

		// Pretty print JSON for readability
		var prettyJSON bytes.Buffer
		err := json.Indent(&prettyJSON, jsonData, "", "  ")
		if err == nil {
			fmt.Println(prettyJSON.String())
		} else {
			fmt.Println(string(jsonData))
		}
		fmt.Printf("===============================\n")
	}

	// Create request
	req, err := http.NewRequest(
		method,
		url,
		bytes.NewBuffer(jsonData))

	if err != nil {
		return errors.New("invalid server parameters")
	}

	// Add authentication header
	var header = viper.GetString("client_id") + " " + viper.GetString("client_secret")
	req.Header.Add("X-Cavaliba-Key", header)
	req.Header.Add("Content-Type", "application/json")

	// Perform request
	resp, err := httpClient.Do(req)
	if err != nil {
		return errors.New("no answer from server")
	}
	defer resp.Body.Close()

	if verbose {
		fmt.Printf("API Response: %d\n", resp.StatusCode)
	}

	// Check HTTP status code
	if resp.StatusCode == 401 {
		return fmt.Errorf("denied")
	}
	if resp.StatusCode == 404 {
		return fmt.Errorf("not found")
	}
	if resp.StatusCode == 405 {
		return fmt.Errorf("method not allowed")
	}
	if resp.StatusCode != 200 && resp.StatusCode != 201 {
		return fmt.Errorf("http error from server (status: %d)", resp.StatusCode)
	}

	// Read response body (for potential error messages)
	bodyBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		return errors.New("can't read server answer")
	}

	if verbose && len(bodyBytes) > 0 {
		fmt.Printf("Response Body:\n%s\n", string(bodyBytes))
		fmt.Printf("====================\n")
	}

	return nil
}
