package notifications

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

	"github.com/gofrs/uuid/v5"
	"github.com/saveinmed/backend-go/internal/domain"
)

type roundTripperFunc func(*http.Request) (*http.Response, error)

func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
	return f(req)
}

func TestRegisterAndUnregisterToken(t *testing.T) {
	svc := NewFCMService("")
	ctx := context.Background()
	userID := uuid.Must(uuid.NewV7())

	if err := svc.RegisterToken(ctx, userID, ""); err == nil {
		t.Fatal("expected error for empty token")
	}

	if err := svc.RegisterToken(ctx, userID, "token-1"); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if err := svc.RegisterToken(ctx, userID, "token-1"); err != nil {
		t.Fatalf("unexpected error on duplicate token: %v", err)
	}

	if len(svc.tokens[userID]) != 1 {
		t.Fatalf("expected 1 token, got %d", len(svc.tokens[userID]))
	}

	if err := svc.UnregisterToken(ctx, userID, "token-1"); err != nil {
		t.Fatalf("unexpected error unregistering: %v", err)
	}

	if len(svc.tokens[userID]) != 0 {
		t.Fatalf("expected no tokens after unregister, got %d", len(svc.tokens[userID]))
	}
}

func TestSendPushSkipsWhenNoTokens(t *testing.T) {
	svc := NewFCMService("")
	ctx := context.Background()

	if err := svc.SendPush(ctx, uuid.Must(uuid.NewV7()), "title", "body", nil); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}

func TestSendToFCMWithServerKey(t *testing.T) {
	svc := NewFCMService("server-key")
	ctx := context.Background()

	var capturedAuth string
	svc.httpClient = &http.Client{
		Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
			capturedAuth = req.Header.Get("Authorization")
			return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("ok"))}, nil
		}),
	}

	err := svc.sendToFCM(ctx, FCMMessage{
		To: "token",
		Notification: &FCMNotification{
			Title: "Hello",
			Body:  "World",
		},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if capturedAuth != "key=server-key" {
		t.Fatalf("expected auth header to include server key, got %q", capturedAuth)
	}
}

func TestSendToFCMRejectsNonOK(t *testing.T) {
	svc := NewFCMService("server-key")
	ctx := context.Background()

	svc.httpClient = &http.Client{
		Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
			return &http.Response{StatusCode: http.StatusBadRequest, Body: io.NopCloser(bytes.NewBufferString("bad"))}, nil
		}),
	}

	if err := svc.sendToFCM(ctx, FCMMessage{To: "token"}); err == nil {
		t.Fatal("expected error for non-OK response")
	}
}

func TestNotifyOrderStatusChangedUsesDefaultEmoji(t *testing.T) {
	svc := NewFCMService("")
	ctx := context.Background()
	buyerID := uuid.Must(uuid.NewV7())

	_ = svc.RegisterToken(ctx, buyerID, "token-1")

	order := &domain.Order{ID: uuid.Must(uuid.NewV7()), Status: domain.OrderStatus("Em análise")}
	buyer := &domain.User{ID: buyerID}

	if err := svc.NotifyOrderStatusChanged(ctx, order, buyer); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}
