package monitor

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"gitea.dooplex.hu/admin/felhom-controller/internal/config"
)

// Pinger sends health check pings to a Healthchecks.io-compatible server.
type Pinger struct {
	baseURL    string
	httpClient *http.Client
	logger     *log.Logger
	enabled    bool
}

// NewPinger creates a new Pinger from monitoring config.
func NewPinger(cfg *config.MonitoringConfig, logger *log.Logger) *Pinger {
	return &Pinger{
		baseURL: strings.TrimRight(cfg.HealthchecksBase, "/"),
		httpClient: &http.Client{
			Timeout: 10 * time.Second,
		},
		logger:  logger,
		enabled: cfg.Enabled,
	}
}

// Ping sends a success signal with optional diagnostic body.
func (p *Pinger) Ping(uuid string, body string) error {
	return p.send(uuid, "", body)
}

// Fail sends a failure signal with diagnostic body.
func (p *Pinger) Fail(uuid string, body string) error {
	return p.send(uuid, "/fail", body)
}

// Start sends a "job started" signal (for duration tracking).
func (p *Pinger) Start(uuid string) error {
	return p.send(uuid, "/start", "")
}

func (p *Pinger) send(uuid, suffix, body string) error {
	if !p.enabled {
		return nil
	}

	if uuid == "" || strings.HasPrefix(uuid, "CHANGEME") {
		return nil
	}

	url := fmt.Sprintf("%s/ping/%s%s", p.baseURL, uuid, suffix)

	var lastErr error
	for attempt := 0; attempt < 3; attempt++ {
		if attempt > 0 {
			time.Sleep(2 * time.Second)
		}

		var bodyReader io.Reader
		if body != "" {
			bodyReader = strings.NewReader(body)
		}

		req, err := http.NewRequest(http.MethodPost, url, bodyReader)
		if err != nil {
			lastErr = err
			continue
		}

		resp, err := p.httpClient.Do(req)
		if err != nil {
			lastErr = err
			continue
		}
		resp.Body.Close()

		if resp.StatusCode >= 200 && resp.StatusCode < 300 {
			return nil
		}
		lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
	}

	p.logger.Printf("[WARN] Health ping failed after 3 attempts (%s): %v", uuid, lastErr)
	return nil // Never let ping failures affect the caller
}
