// Copyright 2026 Moko Consulting <hello@mokoconsulting.tech>
// SPDX-License-Identifier: GPL-3.0-or-later

package mailer

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"

	user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
	sender_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/mailer/sender"
)

// SendUpdateNotification emails the admin and sends ntfy push when a new MokoGitea version is available.
func SendUpdateNotification(version, channel, releaseURL, dockerImage string) {
	subject := fmt.Sprintf("[MokoGitea] Update available: %s (%s)", version, channel)

	body := fmt.Sprintf(`MokoGitea Update Available

A new version is available on the %s channel.

Version:  %s
Channel:  %s
Current:  %s`, channel, version, channel, setting.AppVer)

	if releaseURL != "" {
		body += fmt.Sprintf("\nRelease:  %s", releaseURL)
	}
	if dockerImage != "" {
		body += fmt.Sprintf("\nDocker:   docker pull %s", dockerImage)
	}

	body += fmt.Sprintf("\n\nUpdate the channel in Site Administration > Dashboard.\n\n— %s", setting.AppName)

	// Send email to admin
	if setting.MailService != nil {
		admin, err := user_model.GetAdminUser(context.Background())
		if err != nil {
			log.Error("SendUpdateNotification: GetAdminUser: %v", err)
		} else {
			msg := sender_service.NewMessage(admin.EmailTo(), subject, body)
			msg.Info = "Update notification"
			SendAsync(msg)
			log.Info("Update email sent to %s for version %s [%s]", admin.Email, version, channel)
		}
	}

	// Send ntfy push notification
	if setting.Ntfy.Enabled && setting.Ntfy.ServerURL != "" {
		sendNtfyNotification(subject, body, releaseURL)
	}
}

func sendNtfyNotification(title, body, clickURL string) {
	url := fmt.Sprintf("%s/%s", setting.Ntfy.ServerURL, setting.Ntfy.DefaultTopic)

	req, err := http.NewRequest("POST", url, bytes.NewBufferString(body))
	if err != nil {
		log.Error("ntfy: create request: %v", err)
		return
	}

	req.Header.Set("Title", title)
	req.Header.Set("Priority", "high")
	req.Header.Set("Tags", "arrow_up,mokogitea")
	if clickURL != "" {
		req.Header.Set("Click", clickURL)
	}
	if setting.Ntfy.Token != "" {
		req.Header.Set("Authorization", "Bearer "+setting.Ntfy.Token)
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Error("ntfy: send notification: %v", err)
		return
	}
	defer resp.Body.Close()
	io.Copy(io.Discard, resp.Body)

	if resp.StatusCode >= 300 {
		log.Error("ntfy: unexpected status %d", resp.StatusCode)
		return
	}

	log.Info("ntfy: update notification sent to %s/%s", setting.Ntfy.ServerURL, setting.Ntfy.DefaultTopic)
}
