// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.1

package job

import (
	"context"
	"strings"

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	libprompt "haixun-backend/internal/library/prompt"
	"haixun-backend/internal/library/style8d"
	domai "haixun-backend/internal/model/ai/domain/usecase"
	jobenum "haixun-backend/internal/model/job/domain/enum"
	jobusecase "haixun-backend/internal/model/job/domain/usecase"
	personausecase "haixun-backend/internal/model/persona/domain/usecase"
	"haixun-backend/internal/svc"
	"haixun-backend/internal/types"

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

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

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

func (l *AnalyzeStyle8DFromWorkerLogic) AnalyzeStyle8DFromWorker(req *types.AnalyzeStyle8DReq) (resp *types.AnalyzeStyle8DData, err error) {
	credential, err := l.svcCtx.ThreadsAccount.ResolveWorkerAiCredential(
		l.ctx,
		req.TenantID,
		req.OwnerUID,
		req.ThreadsAccountID,
	)
	if err != nil {
		return nil, err
	}
	providerID, err := mapWorkerAIProvider(credential.Provider)
	if err != nil {
		return nil, err
	}

	posts := make([]style8d.Post, 0, len(req.Posts))
	for _, item := range req.Posts {
		text := strings.TrimSpace(item.Text)
		if text == "" {
			continue
		}
		posts = append(posts, style8d.Post{
			Text:       text,
			Permalink:  strings.TrimSpace(item.Permalink),
			LikeCount:  item.LikeCount,
			ReplyCount: item.ReplyCount,
		})
	}
	if len(posts) == 0 {
		return nil, app.For(code.Persona).InputInvalidFormat("posts contain no readable text")
	}

	steps := toEntitySteps(req.Steps)
	steps = markWorkerStep(steps, "style", jobenum.StepStatusRunning, "AI 正在分析 D1–D8…")
	_, _ = l.svcCtx.Job.UpdateProgress(l.ctx, jobusecase.UpdateProgressRequest{
		JobID:      req.ID,
		WorkerID:   req.WorkerID,
		Phase:      "style",
		Summary:    "AI 正在分析八個風格維度…",
		Percentage: 55,
		Steps:      steps,
	})

	username := strings.TrimPrefix(strings.TrimSpace(req.Username), "@")
	systemPrompt, err := libprompt.Style8DSystem()
	if err != nil {
		return nil, app.For(code.AI).SysInternal("prompt config load failed")
	}
	result, err := l.svcCtx.AI.GenerateText(l.ctx, domai.GenerateRequest{
		Provider: providerID,
		Model:    credential.Model,
		Credential: domai.Credential{
			APIKey: credential.APIKey,
		},
		System: systemPrompt,
		Messages: []domai.Message{
			{Role: "user", Content: style8d.BuildUserPrompt(username, posts)},
		},
	})
	if err != nil {
		if strings.Contains(err.Error(), "HTTP 401") {
			err = app.For(code.AI).SvcThirdParty(
				"8D AI 分析授權失敗：目前帳號的研究用 Provider API key 無效或未授權。請到「設定 > 帳號 AI 設定」確認 research provider=" +
					credential.Provider + "、model=" + credential.Model + "，並重新貼上對應 provider 的 API key",
			)
		}
		return nil, err
	}

	parsed, err := style8d.ParseLLMOutput(result.Text)
	if err != nil {
		return nil, app.For(code.AI).SvcThirdParty("8D LLM 回傳無法解析：" + err.Error())
	}
	profile := style8d.BuildStoredProfile(username, posts, parsed)
	profileJSON, err := profile.JSON()
	if err != nil {
		return nil, err
	}

	steps = markWorkerStep(steps, "style", jobenum.StepStatusSucceeded, "8D 風格策略已產生")
	steps = markWorkerStep(steps, "store", jobenum.StepStatusRunning, "寫入人設風格策略…")
	_, _ = l.svcCtx.Job.UpdateProgress(l.ctx, jobusecase.UpdateProgressRequest{
		JobID:      req.ID,
		WorkerID:   req.WorkerID,
		Phase:      "store",
		Summary:    "8D 分析完成，寫入人設…",
		Percentage: 88,
		Steps:      steps,
	})

	personaDraft := strings.TrimSpace(profile.PersonaDraft)
	patch := personausecase.PersonaPatch{
		StyleProfile:   &profileJSON,
		StyleBenchmark: &username,
	}
	if personaDraft != "" {
		patch.Persona = &personaDraft
	}
	_, err = l.svcCtx.Persona.Update(l.ctx, personausecase.UpdateRequest{
		TenantID:  req.TenantID,
		OwnerUID:  req.OwnerUID,
		PersonaID: req.PersonaID,
		Patch:     patch,
	})
	if err != nil {
		return nil, err
	}

	steps = markWorkerStep(steps, "store", jobenum.StepStatusSucceeded, "8D 策略已寫入人設")
	_, _ = l.svcCtx.Job.UpdateProgress(l.ctx, jobusecase.UpdateProgressRequest{
		JobID:      req.ID,
		WorkerID:   req.WorkerID,
		Phase:      "store",
		Summary:    "8D 策略已寫入人設",
		Percentage: 92,
		Steps:      steps,
	})

	return &types.AnalyzeStyle8DData{
		PersonaID:      req.PersonaID,
		PostCount:      len(posts),
		StyleProfile:   profileJSON,
		StyleBenchmark: username,
	}, nil
}
