package mattermost

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/nomadcode/nomadcode-core/internal/notification"
)

func TestTaskNotificationSinkFailsForCompletedOnly(t *testing.T) {
	var posts []postRequest
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/api/v4/posts" {
			t.Fatalf("path: got %s, want /api/v4/posts", r.URL.Path)
		}
		if got := r.Header.Get("Authorization"); got != "Bearer test-token" {
			t.Fatalf("authorization: got %q", got)
		}
		var body postRequest
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			t.Fatalf("decode request: %v", err)
		}
		posts = append(posts, body)
		w.WriteHeader(http.StatusCreated)
	}))
	defer server.Close()

	client := NewClientWithHTTPClient(Config{
		BaseURL:   server.URL,
		Token:     "test-token",
		ChannelID: "task-channel",
	}, server.Client(), nil)
	sink := NewTaskNotificationSink(client)

	events := []notification.TaskEvent{
		{
			Type:    notification.TaskEventRunning,
			TaskID:  "task-running",
			Title:   "Running Task",
			Status:  "running",
			Message: "started",
		},
		{
			Type:    notification.TaskEventFailed,
			TaskID:  "task-failed",
			Title:   "Failed Task",
			Status:  "failed",
			Message: "failed",
		},
		{
			Type:    notification.TaskEventCompleted,
			TaskID:  "task-completed",
			Title:   "Completed Task",
			Status:  "completed",
			Message: "done",
		},
	}

	for _, event := range events {
		if err := sink.HandleTaskEvent(context.Background(), event); err != nil {
			t.Fatalf("HandleTaskEvent(%s) returned error: %v", event.Type, err)
		}
	}

	if len(posts) != 1 {
		t.Fatalf("posts: got %d, want 1", len(posts))
	}
	if got := posts[0].ChannelID; got != "task-channel" {
		t.Fatalf("channel_id: got %q, want task-channel", got)
	}
	for _, want := range []string{"Completed Task", "task-completed", "completed", "done"} {
		if !strings.Contains(posts[0].Message, want) {
			t.Fatalf("message %q does not contain %q", posts[0].Message, want)
		}
	}
}

func TestTaskNotificationSinkIsNoopWithNilClient(t *testing.T) {
	sink := NewTaskNotificationSink(nil)

	events := []notification.TaskEvent{
		{Type: notification.TaskEventCompleted, TaskID: "task-1", Status: "completed"},
		{Type: notification.TaskEventRunning, TaskID: "task-2", Status: "running"},
	}

	for _, event := range events {
		if err := sink.HandleTaskEvent(context.Background(), event); err != nil {
			t.Fatalf("HandleTaskEvent(%s) with nil client: unexpected error: %v", event.Type, err)
		}
	}
}

func TestTaskNotificationSinkPropagatesMattermostError(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "mattermost unavailable", http.StatusBadGateway)
	}))
	defer server.Close()

	client := NewClientWithHTTPClient(Config{
		BaseURL:   server.URL,
		Token:     "test-token",
		ChannelID: "task-channel",
	}, server.Client(), nil)
	sink := NewTaskNotificationSink(client)

	err := sink.HandleTaskEvent(context.Background(), notification.TaskEvent{
		Type:    notification.TaskEventCompleted,
		TaskID:  "task-completed",
		Title:   "Completed Task",
		Status:  "completed",
		Message: "done",
	})
	if err == nil {
		t.Fatal("expected error")
	}
	errText := err.Error()
	if !strings.Contains(errText, "status 502") || !strings.Contains(errText, "mattermost unavailable") {
		t.Fatalf("unexpected error: %v", err)
	}
}
