// Package notify sends owner notifications (unlock/renewal notices).
// Channels: ntfy (self-hosted, default), SMS (via the sms.Sender), or both,
// selected by NOTIFY_CHANNEL=ntfy|sms|both.
package notify

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"wherewoof/frontend/internal/sms"
)

// Notifier delivers messages to the owner.
type Notifier struct {
	sender sms.Sender // used when the SMS channel is enabled
	client *http.Client
}

// New builds a Notifier. sender may be nil (SMS channel disabled).
func New(sender sms.Sender) *Notifier {
	return &Notifier{sender: sender, client: &http.Client{Timeout: 10 * time.Second}}
}

// Channel returns the configured channel: ntfy (default), sms, or both.
func (n *Notifier) Channel() string {
	c := os.Getenv("NOTIFY_CHANNEL")
	if c != "sms" && c != "both" {
		return "ntfy"
	}
	return c
}

// Send delivers the message to the owner's phone (SMS) and/or the ntfy topic.
// Unlock notices are system messages — they are NOT subject to SMS metering.
func (n *Notifier) Send(ownerPhone, message string) {
	ch := n.Channel()
	if ch == "sms" || ch == "both" {
		if n.sender != nil {
			if err := n.sender.Send(sms.NormalizeAU(ownerPhone), message); err != nil {
				log.Println("notify sms failed:", err)
			}
		} else {
			log.Println("notify: SMS channel selected but no sender configured")
		}
	}
	if ch == "ntfy" || ch == "both" {
		n.sendNtfy(message)
	}
}

func (n *Notifier) sendNtfy(message string) {
	url := os.Getenv("NTFY_URL")
	if url == "" {
		url = "https://ntfy.sh"
	}
	topic := os.Getenv("NTFY_TOPIC")
	if topic == "" {
		topic = "wherewoof-owner-alerts"
	}
	req, err := http.NewRequest(http.MethodPost, url+"/"+topic, bytes.NewBufferString(message))
	if err != nil {
		log.Println("notify ntfy:", err)
		return
	}
	req.Header.Set("Title", "Where Woof")
	resp, err := n.client.Do(req)
	if err != nil {
		log.Println("notify ntfy failed:", err)
		return
	}
	resp.Body.Close()
	if resp.StatusCode >= 300 {
		log.Printf("notify ntfy: status %d", resp.StatusCode)
	}
}

// UnlockMessage builds the owner notice for a gated scan.
func UnlockMessage(tagCode, reason string) string {
	switch reason {
	case "lapsed":
		return fmt.Sprintf("Where Woof: your tag %s was scanned, but your plan is lapsed. Renew to see the finder's details: https://where-woof.com/account", tagCode)
	case "credits":
		return fmt.Sprintf("Where Woof: your tag %s was scanned, but you're out of SMS credits. Top up or renew to see the finder's details: https://where-woof.com/account", tagCode)
	default:
		return fmt.Sprintf("Where Woof: your tag %s was scanned. Manage your plan: https://where-woof.com/account", tagCode)
	}
}
