package email_test

import (
	"strings"
	"testing"

	emailpkg "{{GO_MODULE}}/pkg/email"
	"{{GO_MODULE}}/services/{{COMPONENT_NAME}}/internal/email"
)

var testBrand = emailpkg.BrandConfig{
	AppName:      "Test App",
	AppURL:       "https://example.com",
	SupportEmail: "support@example.com",
	PrimaryColor: "#6366f1",
}

func newTestRenderer(t *testing.T) *emailpkg.Renderer {
	t.Helper()
	r, err := emailpkg.NewRendererFromFS(email.TemplateFS, "templates", testBrand)
	if err != nil {
		t.Fatalf("NewRendererFromFS: %v", err)
	}
	return r
}

func TestRendererLoads(t *testing.T) {
	r := newTestRenderer(t)

	purposes := r.Purposes()
	want := []string{"email_verify", "login_otp", "magic_link", "password_reset", "welcome"}
	if len(purposes) != len(want) {
		t.Fatalf("expected %d purposes, got %d: %v", len(want), len(purposes), purposes)
	}
	for i, p := range want {
		if purposes[i] != p {
			t.Errorf("purpose[%d]: want %q, got %q", i, p, purposes[i])
		}
	}
}

func TestRenderLoginOTP(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("login_otp", emailpkg.EmailContext{
		Code:      "482916",
		ExpiresIn: 10,
		Purpose:   "sign in",
	})
	if err != nil {
		t.Fatalf("Render login_otp: %v", err)
	}
	if out.Subject == "" {
		t.Error("Subject is empty")
	}
	if !strings.Contains(out.Subject, "Test App") {
		t.Errorf("Subject %q does not contain app name", out.Subject)
	}
	if !strings.Contains(out.HTML, "482916") {
		t.Error("HTML does not contain OTP code")
	}
	if !strings.Contains(out.HTML, "code-box") {
		t.Error("HTML does not contain code-box element")
	}
	if out.PlainText == "" {
		t.Error("PlainText is empty")
	}
	if !strings.Contains(out.PlainText, "482916") {
		t.Error("PlainText does not contain OTP code")
	}
	if out.Preheader == "" {
		t.Error("Preheader is empty")
	}
}

func TestRenderMagicLink(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("magic_link", emailpkg.EmailContext{
		ActionURL:  "https://example.com/auth/verify?token=abc123",
		ButtonText: "Sign In \u2192",
		ExpiresIn:  15,
	})
	if err != nil {
		t.Fatalf("Render magic_link: %v", err)
	}
	if !strings.Contains(out.HTML, "Sign In") {
		t.Error("HTML does not contain button text")
	}
	if !strings.Contains(out.HTML, "auth/verify") {
		t.Error("HTML does not contain action URL")
	}
	if out.PlainText == "" {
		t.Error("PlainText is empty")
	}
}

func TestRenderPasswordReset(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("password_reset", emailpkg.EmailContext{
		ActionURL:  "https://example.com/auth/reset?token=xyz789",
		ButtonText: "Reset Password \u2192",
		ExpiresIn:  60,
	})
	if err != nil {
		t.Fatalf("Render password_reset: %v", err)
	}
	if !strings.Contains(out.HTML, "Reset Password") {
		t.Error("HTML does not contain button text")
	}
	if !strings.Contains(out.Subject, "Reset") {
		t.Errorf("Subject %q does not mention reset", out.Subject)
	}
}

func TestRenderVerifyEmail(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("email_verify", emailpkg.EmailContext{
		Code:      "738201",
		ExpiresIn: 30,
		Purpose:   "verify your email",
	})
	if err != nil {
		t.Fatalf("Render email_verify: %v", err)
	}
	if !strings.Contains(out.HTML, "738201") {
		t.Error("HTML does not contain verification code")
	}
	if !strings.Contains(out.HTML, "code-box") {
		t.Error("HTML does not contain code-box element")
	}
}

func TestRenderWelcome(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("welcome", emailpkg.EmailContext{
		ActionURL:  "https://example.com/dashboard",
		ButtonText: "Get Started \u2192",
		Name:       "Jordan",
	})
	if err != nil {
		t.Fatalf("Render welcome: %v", err)
	}
	if !strings.Contains(out.HTML, "Jordan") {
		t.Error("HTML does not contain user name")
	}
	if !strings.Contains(out.HTML, "Welcome") {
		t.Error("HTML does not contain welcome heading")
	}
}

func TestBrandColorInjection(t *testing.T) {
	r := newTestRenderer(t)
	out, err := r.Render("login_otp", emailpkg.EmailContext{
		Code:      "123456",
		ExpiresIn: 10,
	})
	if err != nil {
		t.Fatalf("Render: %v", err)
	}
	// Brand primary color should appear in the inlined styles.
	if !strings.Contains(out.HTML, "#6366f1") {
		t.Error("HTML does not contain brand color #6366f1")
	}
}

func TestUnknownPurposeReturnsError(t *testing.T) {
	r := newTestRenderer(t)
	_, err := r.Render("nonexistent_type", emailpkg.EmailContext{})
	if err == nil {
		t.Error("expected error for unknown purpose, got nil")
	}
}

func TestAllTemplatesHaveSubjectAndPreheader(t *testing.T) {
	r := newTestRenderer(t)
	contexts := map[string]emailpkg.EmailContext{
		"login_otp":      {Code: "111111", ExpiresIn: 10},
		"magic_link":     {ActionURL: "https://example.com/auth", ButtonText: "Sign In", ExpiresIn: 15},
		"password_reset": {ActionURL: "https://example.com/reset", ButtonText: "Reset", ExpiresIn: 60},
		"email_verify":   {Code: "222222", ExpiresIn: 30},
		"welcome":        {ActionURL: "https://example.com", ButtonText: "Get Started", Name: "Alex"},
	}
	for _, purpose := range r.Purposes() {
		ctx := contexts[purpose]
		out, err := r.Render(purpose, ctx)
		if err != nil {
			t.Errorf("%s: render error: %v", purpose, err)
			continue
		}
		if out.Subject == "" {
			t.Errorf("%s: Subject is empty", purpose)
		}
		if out.Preheader == "" {
			t.Errorf("%s: Preheader is empty", purpose)
		}
		if out.HTML == "" {
			t.Errorf("%s: HTML is empty", purpose)
		}
		if out.PlainText == "" {
			t.Errorf("%s: PlainText is empty", purpose)
		}
	}
}
