package main

import "testing"

func TestDecideTrigger_MentionInIssueComment(t *testing.T) {
	body := []byte(`{
		"action": "created",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo", "ssh_url": "git@host:lars/demo.git", "default_branch": "main"},
		"issue": {"number": 7, "user": {"login": "lars"}, "html_url": "http://h/lars/demo/issues/7"},
		"comment": {"id": 1, "body": "@klaus please look at this", "user": {"login": "lars"}}
	}`)
	_, tr, err := DecideTrigger("issue_comment", body)
	if err != nil {
		t.Fatal(err)
	}
	if tr == nil {
		t.Fatal("expected trigger, got nil")
	}
	if tr.Reason != "mention" || tr.Number != 7 || tr.IsPR {
		t.Fatalf("unexpected trigger: %+v", tr)
	}
}

func TestDecideTrigger_AssignedPR(t *testing.T) {
	body := []byte(`{
		"action": "assigned",
		"sender": {"login": "lars"},
		"assignee": {"login": "Klaus"},
		"repository": {"full_name": "lars/demo", "ssh_url": "git@host:lars/demo.git", "default_branch": "main"},
		"pull_request": {"number": 12, "head": {"ref": "feat-x"}, "user": {"login": "lars"}}
	}`)
	_, tr, err := DecideTrigger("pull_request", body)
	if err != nil {
		t.Fatal(err)
	}
	if tr == nil || tr.Reason != "assigned" || !tr.IsPR || tr.Number != 12 || tr.BranchHint != "feat-x" {
		t.Fatalf("unexpected trigger: %+v", tr)
	}
}

func TestDecideTrigger_ReplyOnKlausPR(t *testing.T) {
	body := []byte(`{
		"action": "created",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo", "ssh_url": "git@host:lars/demo.git", "default_branch": "main"},
		"issue": {"number": 5, "user": {"login": "klaus"}, "pull_request": {"html_url": "x"}},
		"comment": {"id": 9, "body": "looks good", "user": {"login": "lars"}}
	}`)
	_, tr, err := DecideTrigger("issue_comment", body)
	if err != nil {
		t.Fatal(err)
	}
	if tr == nil || tr.Reason != "reply_on_klaus_pr" || !tr.IsPR {
		t.Fatalf("unexpected trigger: %+v", tr)
	}
}

func TestDecideTrigger_IgnoresOwnEvents(t *testing.T) {
	body := []byte(`{
		"action": "created",
		"sender": {"login": "klaus"},
		"repository": {"full_name": "lars/demo"},
		"issue": {"number": 1, "user": {"login": "lars"}},
		"comment": {"body": "@klaus hi", "user": {"login": "klaus"}}
	}`)
	_, tr, err := DecideTrigger("issue_comment", body)
	if err != nil {
		t.Fatal(err)
	}
	if tr != nil {
		t.Fatalf("expected nil trigger for self-event, got %+v", tr)
	}
}

func TestDecideTrigger_NoMentionNoTrigger(t *testing.T) {
	body := []byte(`{
		"action": "created",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo"},
		"issue": {"number": 2, "user": {"login": "lars"}},
		"comment": {"body": "thanks everyone", "user": {"login": "lars"}}
	}`)
	_, tr, _ := DecideTrigger("issue_comment", body)
	if tr != nil {
		t.Fatalf("expected nil trigger, got %+v", tr)
	}
}

func TestDecideTrigger_EditedCommentAddsMention(t *testing.T) {
	body := []byte(`{
		"action": "edited",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo"},
		"issue": {"number": 21, "user": {"login": "Klaus"}},
		"comment": {"id": 31, "body": "@Klaus Please respond", "user": {"login": "lars"}},
		"changes": {"body": {"from": "Hello? Can you hear me?"}}
	}`)
	_, tr, err := DecideTrigger("issue_comment", body)
	if err != nil {
		t.Fatal(err)
	}
	if tr == nil || tr.Reason != "mention" || tr.Number != 21 {
		t.Fatalf("expected mention trigger, got %+v", tr)
	}
}

func TestDecideTrigger_EditedCommentAlreadyMentioned(t *testing.T) {
	// Mention was in the original body too — do not re-trigger.
	body := []byte(`{
		"action": "edited",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo"},
		"issue": {"number": 21, "user": {"login": "lars"}},
		"comment": {"id": 31, "body": "@Klaus please look (typo fixed)", "user": {"login": "lars"}},
		"changes": {"body": {"from": "@Klaus please look (typo)"}}
	}`)
	_, tr, _ := DecideTrigger("issue_comment", body)
	if tr != nil {
		t.Fatalf("expected nil trigger (mention pre-existed), got %+v", tr)
	}
}

func TestDecideTrigger_EditedNonBodyChange(t *testing.T) {
	// changes present but no body field — e.g. labels changed. Should not trigger.
	body := []byte(`{
		"action": "edited",
		"sender": {"login": "lars"},
		"repository": {"full_name": "lars/demo"},
		"issue": {"number": 1, "body": "@Klaus help", "user": {"login": "lars"}},
		"changes": {"added_labels": null}
	}`)
	_, tr, _ := DecideTrigger("issues", body)
	if tr != nil {
		t.Fatalf("expected nil trigger when body wasn't part of edit, got %+v", tr)
	}
}

func TestMentionRegex_NotPartOfWord(t *testing.T) {
	cases := map[string]bool{
		"hello @klaus please":         true,
		"@klaus do x":                 true,
		"thanks @KLAUS":               true,
		"email me at not@klausmail":   false,
		"see klausbot":                false,
		"@klausen is someone else":    false,
	}
	for in, want := range cases {
		if got := mentionsKlaus(in); got != want {
			t.Errorf("mentionsKlaus(%q) = %v, want %v", in, got, want)
		}
	}
}
