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

package ntfy

import (
	"context"
	"fmt"

	actions_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/actions"
	issues_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/issues"
	repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
	user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
	"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
	notify_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/notify"
)

func init() {
	if setting.Ntfy.Enabled {
		notify_service.RegisterNotifier(NewNotifier())
	}
}

type ntfyNotifier struct {
	notify_service.NullNotifier
}

// NewNotifier creates a new ntfy notifier.
func NewNotifier() notify_service.Notifier {
	return &ntfyNotifier{}
}

func (*ntfyNotifier) Run() {}

func repoTopic(repo *repo_model.Repository) string {
	if repo == nil {
		return setting.Ntfy.DefaultTopic
	}
	return setting.Ntfy.DefaultTopic
}

func (*ntfyNotifier) NewIssue(_ context.Context, issue *issues_model.Issue, _ []*user_model.User) {
	_ = issue.LoadRepo(context.Background())
	SendAsync(repoTopic(issue.Repo),
		fmt.Sprintf("New Issue: %s", issue.Title),
		fmt.Sprintf("#%d in %s\n%s", issue.Index, issue.Repo.FullName(), issue.Content),
		"default",
		"issue,new")
}

func (*ntfyNotifier) IssueChangeStatus(_ context.Context, doer *user_model.User, _ string, issue *issues_model.Issue, _ *issues_model.Comment, closeOrReopen bool) {
	_ = issue.LoadRepo(context.Background())
	action := "reopened"
	if !closeOrReopen {
		action = "closed"
	}
	SendAsync(repoTopic(issue.Repo),
		fmt.Sprintf("Issue %s: %s", action, issue.Title),
		fmt.Sprintf("#%d %s by %s", issue.Index, action, doer.Name),
		"low",
		"issue,"+action)
}

func (*ntfyNotifier) NewPullRequest(_ context.Context, pr *issues_model.PullRequest, _ []*user_model.User) {
	_ = pr.LoadIssue(context.Background())
	_ = pr.Issue.LoadRepo(context.Background())
	SendAsync(repoTopic(pr.Issue.Repo),
		fmt.Sprintf("New PR: %s", pr.Issue.Title),
		fmt.Sprintf("#%d in %s\n%s → %s", pr.Issue.Index, pr.Issue.Repo.FullName(), pr.HeadBranch, pr.BaseBranch),
		"default",
		"git-pull-request,new")
}

func (*ntfyNotifier) MergePullRequest(_ context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
	_ = pr.LoadIssue(context.Background())
	_ = pr.Issue.LoadRepo(context.Background())
	SendAsync(repoTopic(pr.Issue.Repo),
		fmt.Sprintf("PR Merged: %s", pr.Issue.Title),
		fmt.Sprintf("#%d merged by %s", pr.Issue.Index, doer.Name),
		"default",
		"git-merge,merged")
}

func (*ntfyNotifier) NewRelease(_ context.Context, rel *repo_model.Release) {
	SendAsync(repoTopic(rel.Repo),
		fmt.Sprintf("New Release: %s", rel.TagName),
		fmt.Sprintf("%s in %s\n%s", rel.TagName, rel.Repo.FullName(), rel.Note),
		"high",
		"rocket,release")
}

func (*ntfyNotifier) WorkflowRunStatusUpdate(_ context.Context, repo *repo_model.Repository, _ *user_model.User, run *actions_model.ActionRun) {
	if run.Status.String() != "success" && run.Status.String() != "failure" {
		return // only notify on completion
	}
	priority := "default"
	tags := "white_check_mark,ci"
	if run.Status.String() == "failure" {
		priority = "high"
		tags = "x,ci-fail"
	}
	SendAsync(repoTopic(repo),
		fmt.Sprintf("CI %s: %s", run.Status.String(), run.Title),
		fmt.Sprintf("Workflow in %s", repo.FullName()),
		priority,
		tags)
}
