package notifications

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"net/http"
	"strings"
	"time"
)

// NtfyChannel POSTs to an ntfy.sh-compatible topic. Per-rule cfg supplies
// "url" (the topic URL, e.g. https://ntfy.sh/my-topic) and optional
// "auth_token" (Bearer).
type NtfyChannel struct {
	HTTP *http.Client
}

func (c *NtfyChannel) Name() string { return "ntfy" }

func (c *NtfyChannel) Send(ctx context.Context, n Notification, cfg map[string]any) (int, error) {
	url, _ := cfg["url"].(string)
	if url == "" {
		return 0, errors.New("ntfy: url required in rule config")
	}
	hc := c.HTTP
	if hc == nil {
		hc = &http.Client{Timeout: 10 * time.Second}
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url,
		bytes.NewReader([]byte(n.Body)))
	if err != nil {
		return 0, err
	}
	req.Header.Set("Title", n.Title)
	if n.URL != "" {
		req.Header.Set("Click", n.URL)
	}
	req.Header.Set("Priority", priorityForSeverity(n.Severity))
	if tag := tagsForSeverity(n.Severity); tag != "" {
		req.Header.Set("Tags", tag)
	}
	if tok, _ := cfg["auth_token"].(string); tok != "" {
		req.Header.Set("Authorization", "Bearer "+strings.TrimSpace(tok))
	}
	resp, err := hc.Do(req)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return 1, nil
	}
	return 0, fmt.Errorf("ntfy: status %d", resp.StatusCode)
}

func priorityForSeverity(s Severity) string {
	switch s {
	case SeverityCritical:
		return "5"
	case SeverityWarning:
		return "4"
	case SeverityDebug:
		return "2"
	default:
		return "3"
	}
}

func tagsForSeverity(s Severity) string {
	switch s {
	case SeverityCritical:
		return "warning,rotating_light"
	case SeverityWarning:
		return "warning"
	case SeverityDebug:
		return "speech_balloon"
	default:
		return "information_source"
	}
}
