package usecase

import (
	"backend/pkg/notification/domain/entity"
	"backend/pkg/notification/domain/template"
	"backend/pkg/notification/domain/usecase"
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestTemplateUseCase_RenderEmailTemplate(t *testing.T) {
	uc := MustTemplateUseCase(TemplateUseCaseParam{
		TemplateRepo: nil,
	})

	ctx := context.Background()

	tests := []struct {
		name           string
		tmpl           template.EmailTemplate
		params         entity.TemplateParams
		expectedSubj   string
		expectedBody   string
		shouldContain  []string
		shouldNotError bool
	}{
		{
			name: "渲染基本參數",
			tmpl: template.EmailTemplate{
				Title: "Hello {{.Username}}",
				Body:  "<p>Your code is: {{.VerifyCode}}</p>",
			},
			params: entity.TemplateParams{
				Username:   "張三",
				VerifyCode: "123456",
			},
			expectedSubj:   "Hello 張三",
			shouldContain:  []string{"123456"},
			shouldNotError: true,
		},
		{
			name: "渲染額外參數",
			tmpl: template.EmailTemplate{
				Title: "Welcome",
				Body:  "<p>Hello {{.Username}}, your link: {{.Link}}</p>",
			},
			params: entity.TemplateParams{
				Username: "John",
				Extra: map[string]string{
					"Link": "https://example.com",
				},
			},
			shouldContain:  []string{"John", "https://example.com"},
			shouldNotError: true,
		},
		{
			name: "特殊字符不轉義（簡單字符串替換）",
			tmpl: template.EmailTemplate{
				Title: "Test",
				Body:  "<p>Name: {{.Username}}</p>",
			},
			params: entity.TemplateParams{
				Username: "<script>alert('xss')</script>",
			},
			shouldContain:  []string{"<script>alert('xss')</script>"}, // 使用簡單字符串替換，不轉義
			shouldNotError: true,
		},
		{
			name: "空模板",
			tmpl: template.EmailTemplate{
				Title: "",
				Body:  "",
			},
			params: entity.TemplateParams{
				Username: "Test",
			},
			expectedSubj:   "",
			expectedBody:   "",
			shouldNotError: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := uc.RenderEmailTemplate(ctx, tt.tmpl, tt.params)

			if tt.shouldNotError {
				assert.NoError(t, err)
				if tt.expectedSubj != "" {
					assert.Equal(t, tt.expectedSubj, result.Subject)
				}
				if tt.expectedBody != "" {
					assert.Equal(t, tt.expectedBody, result.Body)
				}
				for _, contain := range tt.shouldContain {
					assert.Contains(t, result.Body, contain)
				}
			} else {
				assert.Error(t, err)
			}
		})
	}
}

func TestTemplateUseCase_RenderSMSTemplate(t *testing.T) {
	uc := MustTemplateUseCase(TemplateUseCaseParam{
		TemplateRepo: nil,
	})

	ctx := context.Background()

	tests := []struct {
		name           string
		tmpl           usecase.SMSTemplateResp
		params         entity.TemplateParams
		expectedBody   string
		shouldContain  []string
		shouldNotError bool
	}{
		{
			name: "渲染 SMS 驗證碼",
			tmpl: usecase.SMSTemplateResp{
				Body: "您的驗證碼是：{{.VerifyCode}}，請在5分鐘內使用。",
			},
			params: entity.TemplateParams{
				VerifyCode: "654321",
			},
			shouldContain:  []string{"654321", "5分鐘"},
			shouldNotError: true,
		},
		{
			name: "SMS 純文本替換",
			tmpl: usecase.SMSTemplateResp{
				Body: "Hi {{.Username}}, your code: {{.VerifyCode}}",
			},
			params: entity.TemplateParams{
				Username:   "<test>",
				VerifyCode: "111111",
			},
			shouldContain:  []string{"<test>", "111111"}, // 使用簡單字符串替換
			shouldNotError: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := uc.RenderSMSTemplate(ctx, tt.tmpl, tt.params)

			if tt.shouldNotError {
				assert.NoError(t, err)
				if tt.expectedBody != "" {
					assert.Equal(t, tt.expectedBody, result.Body)
				}
				for _, contain := range tt.shouldContain {
					assert.Contains(t, result.Body, contain)
				}
			} else {
				assert.Error(t, err)
			}
		})
	}
}

func TestTemplateUseCase_GetEmailTemplateByStatic(t *testing.T) {
	uc := MustTemplateUseCase(TemplateUseCaseParam{
		TemplateRepo: nil,
	})

	ctx := context.Background()

	tests := []struct {
		name       string
		language   template.Language
		templateID template.Type
		wantErr    bool
	}{
		{
			name:       "獲取忘記密碼模板 (zh-tw)",
			language:   template.LanguageZhTW,
			templateID: template.ForgetPasswordVerify,
			wantErr:    false,
		},
		{
			name:       "獲取綁定郵箱模板 (zh-tw)",
			language:   template.LanguageZhTW,
			templateID: template.BindingEmail,
			wantErr:    false,
		},
		{
			name:       "不存在的語言",
			language:   template.Language("xx-xx"),
			templateID: template.ForgetPasswordVerify,
			wantErr:    true,
		},
		{
			name:       "不存在的模板類型",
			language:   template.LanguageZhTW,
			templateID: template.Type("non_existent"),
			wantErr:    true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, err := uc.GetEmailTemplateByStatic(ctx, tt.language, tt.templateID)

			if tt.wantErr {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
				assert.NotEmpty(t, result.Title)
				assert.NotEmpty(t, result.Body)
			}
		})
	}
}

func TestTemplateUseCase_GetDefaultSMSTemplate(t *testing.T) {
	uc := &TemplateUseCase{}

	tests := []struct {
		name          string
		templateID    template.Type
		shouldContain []string
	}{
		{
			name:          "忘記密碼模板",
			templateID:    template.ForgetPasswordVerify,
			shouldContain: []string{"密碼重設", "驗證碼"},
		},
		{
			name:          "綁定郵箱模板",
			templateID:    template.BindingEmail,
			shouldContain: []string{"綁定", "驗證碼"},
		},
		{
			name:          "默認模板",
			templateID:    template.Type("unknown"),
			shouldContain: []string{"驗證碼"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := uc.getDefaultSMSTemplate(tt.templateID)

			assert.NotEmpty(t, result.Body)
			for _, contain := range tt.shouldContain {
				assert.Contains(t, result.Body, contain)
			}
		})
	}
}
