package copy_mission

import (
	"context"
	"strings"

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	"haixun-backend/internal/library/placement"
	"haixun-backend/internal/library/style8d"
	libviral "haixun-backend/internal/library/viral"
	"haixun-backend/internal/library/websearch"
	domai "haixun-backend/internal/model/ai/domain/usecase"
	aiusecase "haixun-backend/internal/model/ai/usecase"
	"haixun-backend/internal/svc"
	"haixun-backend/internal/types"
)

type InspireCopyMissionLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewInspireCopyMissionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *InspireCopyMissionLogic {
	return &InspireCopyMissionLogic{ctx: ctx, svcCtx: svcCtx}
}

func (l *InspireCopyMissionLogic) InspireCopyMission(req *types.PersonaCopyMissionsPath) (*types.CopyMissionInspirationData, error) {
	tenantID, uid, err := actorFrom(l.ctx)
	if err != nil {
		return nil, err
	}
	personaID := strings.TrimSpace(req.PersonaID)
	persona, err := l.svcCtx.Persona.Get(l.ctx, tenantID, uid, personaID)
	if err != nil {
		return nil, err
	}

	missionList, err := l.svcCtx.CopyMission.List(l.ctx, tenantID, uid, personaID)
	if err != nil {
		return nil, err
	}
	recentLabels := make([]string, 0, 8)
	recentSeeds := make([]string, 0, 8)
	for _, mission := range missionList.List {
		if mission.Status == "archived" {
			continue
		}
		if label := strings.TrimSpace(mission.Label); label != "" {
			recentLabels = append(recentLabels, label)
		}
		if seed := strings.TrimSpace(mission.SeedQuery); seed != "" {
			recentSeeds = append(recentSeeds, seed)
		}
		if len(recentLabels) >= 8 && len(recentSeeds) >= 8 {
			break
		}
	}

	trendSnippets := []libviral.MissionInspireTrendSnippet{}
	webSearchProvider := ""
	llmOnly := true

	research, researchErr := l.svcCtx.Placement.ResearchSettings(l.ctx, tenantID, uid)
	if researchErr == nil && placement.WebSearchAvailable(research) {
		memberCtx, memberErr := l.svcCtx.ThreadsAccount.ResolveMemberPlacementContext(l.ctx, tenantID, uid, research)
		if memberErr == nil {
			webClient := websearch.New(memberCtx.WebSearchConfig())
			trendSnippets = libviral.CollectMissionInspireTrends(
				l.ctx,
				webClient,
				memberCtx,
				persona.Brief,
				persona.StyleBenchmark,
			)
			webSearchProvider = memberCtx.WebSearchProviderLabel()
			llmOnly = len(trendSnippets) == 0
		}
	}
	webSearchUsed := len(trendSnippets) > 0

	credential, err := l.svcCtx.ThreadsAccount.ResolveMemberAiCredential(l.ctx, tenantID, uid)
	if err != nil {
		return nil, err
	}
	providerID, err := aiusecase.MapWorkerProvider(credential.Provider)
	if err != nil {
		return nil, err
	}

	personaBlock := style8d.ResolvePersonaBlock(persona.Persona, persona.StyleProfile, persona.Brief)
	result, err := l.svcCtx.AI.GenerateText(l.ctx, domai.GenerateRequest{
		Provider: providerID,
		Model:    credential.Model,
		Credential: domai.Credential{
			APIKey: credential.APIKey,
		},
		System: libviral.BuildMissionInspireSystemPrompt(),
		Messages: []domai.Message{
			{
				Role: "user",
				Content: libviral.BuildMissionInspireUserPrompt(libviral.MissionInspireInput{
					PersonaDisplayName:  persona.DisplayName,
					PersonaBrief:        persona.Brief,
					PersonaBlock:        personaBlock,
					StyleBenchmark:      persona.StyleBenchmark,
					PersonaAudience:     persona.CopyResearchMap.AudienceSummary,
					PersonaContentGoal:  persona.CopyResearchMap.ContentGoal,
					PersonaQuestions:    append([]string(nil), persona.CopyResearchMap.Questions...),
					PersonaPillars:      append([]string(nil), persona.CopyResearchMap.Pillars...),
					RecentMissionLabels: recentLabels,
					RecentSeedQueries:   recentSeeds,
					TrendSnippets:       trendSnippets,
					WebSearchProvider:   webSearchProvider,
					LLMOnly:             llmOnly,
				}),
			},
		},
	})
	if err != nil {
		return nil, err
	}

	parsed, err := libviral.ParseMissionInspireOutput(result.Text)
	if err != nil {
		return nil, app.For(code.AI).SvcThirdParty("靈感骰子 LLM 回傳無法解析：" + err.Error())
	}

	sources := make([]types.CopyMissionInspirationSourceData, 0, len(trendSnippets))
	for _, item := range trendSnippets {
		sources = append(sources, types.CopyMissionInspirationSourceData{
			Query:   item.Query,
			Title:   item.Title,
			Snippet: item.Snippet,
			URL:     item.URL,
		})
	}

	message := "已依近期趨勢產出任務靈感，可微調後建立任務"
	if !webSearchUsed {
		message = "未設定搜尋 API key，已改由 LLM 依人設推測靈感；補上 Brave／Exa key 可取得更貼近熱搜的結果"
	}

	return &types.CopyMissionInspirationData{
		Label:         parsed.Label,
		SeedQuery:     parsed.SeedQuery,
		Brief:         parsed.Brief,
		TrendReason:   parsed.TrendReason,
		TrendKeywords: parsed.TrendKeywords,
		Sources:       sources,
		WebSearchUsed: webSearchUsed,
		Message:       message,
	}, nil
}
