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

package mailer

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

	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"
)

// SendLoginNotification sends email and ntfy notifications when a user signs in.
func SendLoginNotification(u *user_model.User, ip, userAgent string) {
	if !setting.LoginNotification.Enabled {
		return
	}

	timestamp := time.Now().UTC().Format("2006-01-02 15:04:05 UTC")
	subject := fmt.Sprintf("[%s] New sign-in: %s", setting.AppName, u.Name)

	body := fmt.Sprintf(`New sign-in detected

Account:    %s (%s)
IP Address: %s
Browser:    %s
Time:       %s
Instance:   %s

If this wasn't you, change your password immediately and review your active sessions.

— %s`, u.Name, u.Email, ip, userAgent, timestamp, setting.AppURL, setting.AppName)

	// Email notification
	if setting.MailService != nil && u.Email != "" {
		msg := sender_service.NewMessage(u.EmailTo(), subject, body)
		msg.Info = fmt.Sprintf("Login notification for %s", u.Name)
		SendAsync(msg)
		log.Debug("Login notification email sent to %s", u.Email)
	}

	// ntfy push notification
	if setting.Ntfy.Enabled && setting.Ntfy.ServerURL != "" {
		go sendLoginNtfy(subject, u.Name, ip, timestamp)
	}
}

func sendLoginNtfy(title, username, ip, timestamp string) {
	body := fmt.Sprintf("User: %s\nIP: %s\nTime: %s", username, ip, timestamp)
	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 login: create request: %v", err)
		return
	}

	req.Header.Set("Title", title)
	req.Header.Set("Priority", "default")
	req.Header.Set("Tags", "key,login")
	req.Header.Set("Click", setting.AppURL+"-/admin")
	if setting.Ntfy.Token != "" {
		req.Header.Set("Authorization", "Bearer "+setting.Ntfy.Token)
	}

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

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