package placement_topic

import (
	"context"
	"fmt"
	"strings"

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	jobdom "haixun-backend/internal/model/job/domain/usecase"
	"haixun-backend/internal/svc"
	"haixun-backend/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type StartPlacementTopicOutreachDraftJobLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewStartPlacementTopicOutreachDraftJobLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StartPlacementTopicOutreachDraftJobLogic {
	return &StartPlacementTopicOutreachDraftJobLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx}
}

func (l *StartPlacementTopicOutreachDraftJobLogic) StartPlacementTopicOutreachDraftJob(
	req *types.StartPlacementTopicOutreachDraftJobHandlerReq,
) (*types.StartPlacementTopicOutreachDraftJobsData, error) {
	tenantID, uid, err := actorFrom(l.ctx)
	if err != nil {
		return nil, err
	}
	scope, err := resolveScope(l.ctx, l.svcCtx, tenantID, uid, req.ID)
	if err != nil {
		return nil, err
	}

	scanPostIDs := append([]string{}, req.ScanPostIDs...)
	if id := strings.TrimSpace(req.ScanPostID); id != "" {
		scanPostIDs = append(scanPostIDs, id)
	}
	seen := map[string]struct{}{}
	unique := make([]string, 0, len(scanPostIDs))
	for _, id := range scanPostIDs {
		id = strings.TrimSpace(id)
		if id == "" {
			continue
		}
		if _, ok := seen[id]; ok {
			continue
		}
		seen[id] = struct{}{}
		unique = append(unique, id)
	}
	if len(unique) == 0 {
		return nil, app.For(code.Brand).InputMissingRequired("scan_post_id or scan_post_ids is required")
	}
	if strings.TrimSpace(req.VoicePersonaID) == "" {
		return nil, app.For(code.Brand).InputMissingRequired("voice_persona_id is required")
	}
	if _, err := l.svcCtx.Persona.Get(l.ctx, tenantID, uid, req.VoicePersonaID); err != nil {
		return nil, err
	}

	count := req.Count
	if count <= 0 {
		count = 3
	}
	if count > 4 {
		count = 4
	}

	productID := strings.TrimSpace(req.ProductID)
	if productID == "" {
		productID = strings.TrimSpace(scope.Topic.ProductID)
	}

	jobs := make([]types.StartBrandScanJobData, 0, len(unique))
	for _, scanPostID := range unique {
		if _, err := l.svcCtx.ScanPost.Get(l.ctx, tenantID, uid, scope.BrandID, scanPostID); err != nil {
			return nil, err
		}
		regenerate := false
		if existing, existingErr := l.svcCtx.OutreachDraft.GetLatestByScanPost(
			l.ctx, tenantID, uid, scope.BrandID, scope.TopicID, scanPostID,
		); existingErr == nil && existing != nil && len(existing.Drafts) > 0 {
			regenerate = true
		}
		payload := map[string]any{
			"brand_id":         scope.BrandID,
			"topic_id":         scope.TopicID,
			"scan_post_id":     scanPostID,
			"count":            count,
			"voice_persona_id": strings.TrimSpace(req.VoicePersonaID),
			"regenerate":       regenerate,
		}
		if productID != "" {
			payload["product_id"] = productID
		}
		run, err := l.svcCtx.Job.CreateRun(l.ctx, jobdom.CreateRunRequest{
			TemplateType: "generate-outreach-draft",
			Scope:        "placement_topic",
			ScopeID:      scope.TopicID,
			TenantID:     tenantID,
			OwnerUID:     uid,
			Payload:      payload,
		})
		if err != nil {
			return nil, err
		}
		jobs = append(jobs, types.StartBrandScanJobData{
			JobID:   run.ID.Hex(),
			Status:  string(run.Status),
			Message: "獲客草稿背景任務已建立",
		})
	}

	message := "獲客草稿已在背景執行，可繼續瀏覽其他頁面"
	if len(jobs) > 1 {
		message = fmt.Sprintf("已送出 %d 個獲客草稿背景任務，可繼續瀏覽其他頁面", len(jobs))
	}
	return &types.StartPlacementTopicOutreachDraftJobsData{
		Jobs:    jobs,
		Message: message,
	}, nil
}
