package service import ( "context" "errors" "gorm.io/gorm" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" applogger "github.com/gochat/gochat/pkg/logger" pkgvalidator "github.com/gochat/gochat/pkg/validator" ) // CsatTemplateService implements business logic for CSAT template management. // Reference: Chatwoot app/controllers/api/v1/accounts/inboxes/inbox_csat_templates_controller.rb // CSAT templates are singular resources per inbox — show (get template status), create (submit template), // and analyze (check template quality via Captain AI). type CsatTemplateService struct { repo *repository.CsatTemplateRepo } // NewCsatTemplateService creates a new CsatTemplate service. func NewCsatTemplateService(repo *repository.CsatTemplateRepo) *CsatTemplateService { return &CsatTemplateService{repo: repo} } // CreateCsatTemplateRequest is the DTO for creating a CSAT template. // Reference: Chatwoot InboxCsatTemplatesController#create — params: {message} type CreateCsatTemplateRequest struct { Message string `json:"message" validate:"required,min=1"` } // AnalyzeCsatTemplateRequest is the DTO for analyzing a CSAT template. // Reference: Chatwoot InboxCsatTemplatesController#analyze — params: {message} type AnalyzeCsatTemplateRequest struct { Message string `json:"message" validate:"required,min=1"` } // CsatTemplateAnalysisResult represents the result of a CSAT template quality analysis. // Placeholder implementation — real analysis requires Captain AI integration (WhatsApp template validation). type CsatTemplateAnalysisResult struct { Quality string `json:"quality"` // e.g. "good", "poor", "needs_improvement" Suggestions []string `json:"suggestions"` // improvement suggestions IsApproved bool `json:"is_approved"` // whether template would likely pass WhatsApp approval Message string `json:"message"` // original message analyzed } // ShowTemplateStatus retrieves the CSAT template status for an inbox. // If no template exists, returns nil to indicate "no template configured". // Reference: Chatwoot InboxCsatTemplatesController#show func (s *CsatTemplateService) ShowTemplateStatus(ctx context.Context, inboxID uint) (*model.CsatTemplate, error) { template, err := s.repo.FindByInbox(ctx, inboxID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { // No template configured — return nil to indicate "no template" (handler will return empty response) return nil, nil } return nil, err } return template, nil } // CreateTemplate creates a new CSAT template for an inbox. // If a template already exists for the inbox, updates it instead. // Reference: Chatwoot InboxCsatTemplatesController#create func (s *CsatTemplateService) CreateTemplate(ctx context.Context, inboxID uint, req CreateCsatTemplateRequest) (*model.CsatTemplate, error) { if err := pkgvalidator.ValidateStruct(req); err != nil { return nil, err } // Check if template already exists for this inbox existing, err := s.repo.FindByInbox(ctx, inboxID) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err } if existing != nil { // Update existing template existing.Message = req.Message existing.Status = "pending" // Reset status to pending after message change if err := s.repo.Update(ctx, existing); err != nil { return nil, err } applogger.L().Infof("CSAT template updated for inbox %d", inboxID) return existing, nil } // Create new template template := &model.CsatTemplate{ InboxID: inboxID, Message: req.Message, Status: "pending", } if err := s.repo.Create(ctx, template); err != nil { return nil, err } applogger.L().Infof("CSAT template created for inbox %d", inboxID) return template, nil } // AnalyzeTemplate analyzes a CSAT template message for quality. // Placeholder implementation — real WhatsApp template analysis requires Captain AI integration. // Reference: Chatwoot InboxCsatTemplatesController#analyze (captain_enabled check) func (s *CsatTemplateService) AnalyzeTemplate(ctx context.Context, inboxID uint, req AnalyzeCsatTemplateRequest) (*CsatTemplateAnalysisResult, error) { if err := pkgvalidator.ValidateStruct(req); err != nil { return nil, err } // Placeholder analysis logic — real implementation would use Captain AI // to validate template against WhatsApp Business API requirements. result := &CsatTemplateAnalysisResult{ Message: req.Message, Quality: "good", IsApproved: true, Suggestions: []string{}, } // Basic heuristic checks if len(req.Message) < 10 { result.Quality = "poor" result.IsApproved = false result.Suggestions = append(result.Suggestions, "Message is too short for a CSAT survey template") } if len(req.Message) > 500 { result.Quality = "needs_improvement" result.Suggestions = append(result.Suggestions, "Message may be too long for WhatsApp template approval") } applogger.L().Infof("CSAT template analyzed for inbox %d, quality=%s", inboxID, result.Quality) return result, nil }