// Package notify sends operational alerts via Telegram and Resend email.
// Credentials are read exclusively from environment variables — never from
// the config file or source code.
package notify

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"

	"forge.secuaas.ovh/olivier/claude-failover/internal/config"
)

// Notifier dispatches alerts to configured sinks.
// All methods are safe to call when credentials are absent — they become no-ops.
type Notifier struct {
	telegramToken   string
	telegramChatID  string
	resendAPIKey    string
	notifyEmail     string
	httpClient      *http.Client
	telegramBaseURL string // override in tests
	resendBaseURL   string // override in tests
}

// New creates a Notifier, reading credentials from the environment variables
// named in cfg.Notifications.
func New(cfg *config.Config) *Notifier {
	n := &Notifier{
		httpClient:      &http.Client{Timeout: 10 * time.Second},
		telegramBaseURL: "https://api.telegram.org",
		resendBaseURL:   "https://api.resend.com",
	}
	if cfg.Notifications.TelegramTokenEnv != "" {
		n.telegramToken = os.Getenv(cfg.Notifications.TelegramTokenEnv)
	}
	if cfg.Notifications.TelegramChatIDEnv != "" {
		n.telegramChatID = os.Getenv(cfg.Notifications.TelegramChatIDEnv)
	}
	if cfg.Notifications.ResendAPIKeyEnv != "" {
		n.resendAPIKey = os.Getenv(cfg.Notifications.ResendAPIKeyEnv)
	}
	n.notifyEmail = "admin@example.com"
	if cfg.Notifications.NotifyEmailEnv != "" {
		if v := os.Getenv(cfg.Notifications.NotifyEmailEnv); v != "" {
			n.notifyEmail = v
		}
	}
	return n
}

// Telegram sends msg to the configured Telegram chat.
// Returns nil (no-op) when token or chat ID is not configured.
func (n *Notifier) Telegram(msg string) error {
	if n.telegramToken == "" || n.telegramChatID == "" {
		return nil
	}
	url := fmt.Sprintf("%s/bot%s/sendMessage", n.telegramBaseURL, n.telegramToken)
	body := map[string]string{
		"chat_id":    n.telegramChatID,
		"text":       msg,
		"parse_mode": "HTML",
	}
	data, _ := json.Marshal(body)
	resp, err := n.httpClient.Post(url, "application/json", bytes.NewReader(data))
	if err != nil {
		return fmt.Errorf("telegram: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 400 {
		return fmt.Errorf("telegram: HTTP %d", resp.StatusCode)
	}
	return nil
}

// Email sends an HTML email via the Resend API.
// Returns nil (no-op) when the API key is not configured.
func (n *Notifier) Email(subject, htmlBody string) error {
	if n.resendAPIKey == "" {
		return nil
	}
	type emailReq struct {
		From    string   `json:"from"`
		To      []string `json:"to"`
		Subject string   `json:"subject"`
		HTML    string   `json:"html"`
	}
	payload := emailReq{
		From:    "Orchestrator <noreply@example.com>",
		To:      []string{n.notifyEmail},
		Subject: subject,
		HTML:    htmlBody,
	}
	data, _ := json.Marshal(payload)
	req, err := http.NewRequest(http.MethodPost, n.resendBaseURL+"/emails", bytes.NewReader(data))
	if err != nil {
		return fmt.Errorf("email: build request: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+n.resendAPIKey)
	req.Header.Set("Content-Type", "application/json")
	resp, err := n.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("email: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 400 {
		return fmt.Errorf("email: HTTP %d", resp.StatusCode)
	}
	return nil
}
