package usecase

import (
	"backend/pkg/notification/domain/entity"
	"backend/pkg/notification/domain/repository"
	"backend/pkg/notification/domain/template"
	"backend/pkg/notification/domain/usecase"
	"context"
	"fmt"
	"strings"

	errs "backend/pkg/library/errors"
)

type TemplateUseCaseParam struct {
	TemplateRepo repository.TemplateRepository // 可選的資料庫模板 repository
	Logger       errs.Logger                   // 日誌記錄器
}

type TemplateUseCase struct {
	param TemplateUseCaseParam
}

func MustTemplateUseCase(param TemplateUseCaseParam) usecase.TemplateUseCase {
	return &TemplateUseCase{
		param,
	}
}

// GetEmailTemplateByStatic 從靜態模板獲取郵件模板
func (use *TemplateUseCase) GetEmailTemplateByStatic(_ context.Context, language template.Language, templateID template.Type) (template.EmailTemplate, error) {
	// 查找指定語言的模板映射
	templateByLang, exists := template.EmailTemplateMap[language]
	if !exists {
		return template.EmailTemplate{}, errs.ResNotFoundError(fmt.Sprintf("email template not found for language: %s", language))
	}

	// 查找指定類型的模板生成函數
	templateFunc, exists := templateByLang[templateID]
	if !exists {
		return template.EmailTemplate{}, errs.ResNotFoundError(fmt.Sprintf("email template not found for type ID: %s", templateID))
	}

	// 執行模板生成函數
	tmp, err := templateFunc()
	if err != nil {
		return template.EmailTemplate{}, errs.DBErrorError(fmt.Sprintf("error generating email template: %v", err))
	}

	return tmp, nil
}

// GetEmailTemplate 獲取郵件模板（優先從資料庫，回退到靜態模板）
func (use *TemplateUseCase) GetEmailTemplate(ctx context.Context, language template.Language, templateID template.Type) (template.EmailTemplate, error) {
	// 1. 嘗試從資料庫獲取模板
	if use.param.TemplateRepo != nil {
		dbTemplate, err := use.param.TemplateRepo.GetTemplate(ctx, "email", string(language), string(templateID))
		if err == nil && dbTemplate != nil && dbTemplate.IsActive {
			return template.EmailTemplate{
				Title: dbTemplate.Subject,
				Body:  dbTemplate.Body,
			}, nil
		}

		// 記錄資料庫查詢失敗，但不返回錯誤，繼續使用靜態模板
		if err != nil {
			_ = errs.DBErrorErrorL(use.param.Logger,
				[]errs.LogField{
					{Key: "type", Val: "email"},
					{Key: "language", Val: string(language)},
					{Key: "template_id", Val: string(templateID)},
					{Key: "func", Val: "TemplateRepo.GetTemplate"},
					{Key: "err", Val: err.Error()},
				},
				"Failed to get template from database, falling back to static")
		}
	}

	// 2. 回退到靜態模板
	return use.GetEmailTemplateByStatic(ctx, language, templateID)
}

// GetSMSTemplate 獲取 SMS 模板（優先從資料庫，回退到靜態模板）
func (use *TemplateUseCase) GetSMSTemplate(ctx context.Context, language template.Language, templateID template.Type) (usecase.SMSTemplateResp, error) {
	// 1. 嘗試從資料庫獲取模板
	if use.param.TemplateRepo != nil {
		dbTemplate, err := use.param.TemplateRepo.GetTemplate(ctx, "sms", string(language), string(templateID))
		if err == nil && dbTemplate != nil && dbTemplate.IsActive {
			return usecase.SMSTemplateResp{
				Body: dbTemplate.Body,
			}, nil
		}

		// 記錄資料庫查詢失敗，但不返回錯誤，繼續使用靜態模板
		if err != nil {
			_ = errs.DBErrorErrorL(use.param.Logger,
				[]errs.LogField{
					{Key: "type", Val: "sms"},
					{Key: "language", Val: string(language)},
					{Key: "template_id", Val: string(templateID)},
					{Key: "func", Val: "TemplateRepo.GetTemplate"},
					{Key: "err", Val: err.Error()},
				},
				"Failed to get SMS template from database, falling back to static")
		}
	}

	// 2. 回退到靜態模板（SMS 暫時沒有靜態模板，返回默認）
	return use.getDefaultSMSTemplate(templateID), nil
}

// RenderEmailTemplate 渲染郵件模板（替換變數）
func (use *TemplateUseCase) RenderEmailTemplate(ctx context.Context, tmpl template.EmailTemplate, params entity.TemplateParams) (usecase.EmailTemplateResp, error) {
	renderedSubject := use.renderTemplate(tmpl.Title, params)
	renderedBody := use.renderTemplate(tmpl.Body, params)

	return usecase.EmailTemplateResp{
		Subject: renderedSubject,
		Body:    renderedBody,
	}, nil
}

// RenderSMSTemplate 渲染 SMS 模板（替換變數）
func (use *TemplateUseCase) RenderSMSTemplate(ctx context.Context, tmpl usecase.SMSTemplateResp, params entity.TemplateParams) (usecase.SMSTemplateResp, error) {
	renderedBody := use.renderTemplate(tmpl.Body, params)

	return usecase.SMSTemplateResp{
		Body: renderedBody,
	}, nil
}

// renderTemplate 渲染模板內容（簡單的字符串替換）
func (use *TemplateUseCase) renderTemplate(content string, params entity.TemplateParams) string {
	result := content

	// 替換基本參數
	result = strings.ReplaceAll(result, "{{.Username}}", params.Username)
	result = strings.ReplaceAll(result, "{{.VerifyCode}}", params.VerifyCode)

	// 替換額外參數
	for key, value := range params.Extra {
		placeholder := fmt.Sprintf("{{.%s}}", key)
		result = strings.ReplaceAll(result, placeholder, value)
	}

	return result
}

// getDefaultSMSTemplate 獲取默認 SMS 模板
func (use *TemplateUseCase) getDefaultSMSTemplate(templateID template.Type) usecase.SMSTemplateResp {
	switch templateID {
	case template.ForgetPasswordVerify:
		return usecase.SMSTemplateResp{
			Body: "您的密碼重設驗證碼是：{{.VerifyCode}}，請在5分鐘內使用。如非本人操作請忽略此訊息。",
		}
	case template.BindingEmail:
		return usecase.SMSTemplateResp{
			Body: "您的綁定驗證碼是：{{.VerifyCode}}，請在5分鐘內使用。如非本人操作請忽略此訊息。",
		}
	default:
		return usecase.SMSTemplateResp{
			Body: "您的驗證碼是：{{.VerifyCode}}，請在5分鐘內使用。",
		}
	}
}
