package persona

import (
	"context"
	"fmt"
	"strings"

	app "haixun-backend/internal/library/errors"
	"haixun-backend/internal/library/errors/code"
	libformula "haixun-backend/internal/library/formula"
	"haixun-backend/internal/library/placement"
	"haixun-backend/internal/library/style8d"
	"haixun-backend/internal/library/websearch"
	domai "haixun-backend/internal/model/ai/domain/usecase"
	aiusecase "haixun-backend/internal/model/ai/usecase"
	copydraftentity "haixun-backend/internal/model/copy_draft/domain/entity"
	copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase"
	"haixun-backend/internal/svc"
	"haixun-backend/internal/types"
)

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

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

func (l *GenerateFromContentFormulaLogic) GenerateFromContentFormula(req *types.GenerateFromContentFormulaHandlerReq) (*types.GenerateFromContentFormulaData, error) {
	tenantID, uid, err := actorFrom(l.ctx)
	if err != nil {
		return nil, err
	}
	personaID := strings.TrimSpace(req.ID)
	topic := strings.TrimSpace(req.Topic)
	if topic == "" {
		return nil, app.For(code.Persona).InputMissingRequired("topic is required")
	}
	persona, err := l.svcCtx.Persona.Get(l.ctx, tenantID, uid, personaID)
	if err != nil {
		return nil, err
	}
	if !style8d.HasReady8D(persona.Persona, persona.StyleProfile) {
		return nil, app.For(code.Persona).InputMissingRequired("請先完成人設 8D 對標分析")
	}
	formula, err := l.svcCtx.ContentFormula.Get(l.ctx, tenantID, uid, req.AccountID, req.FormulaID)
	if err != nil {
		return nil, err
	}
	count := req.DraftCount
	if count <= 0 {
		count = 1
	}
	if count > 5 {
		count = 5
	}

	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
	}
	aiReq := domai.GenerateRequest{
		Provider:   providerID,
		Model:      credential.Model,
		Credential: domai.Credential{APIKey: credential.APIKey},
	}
	personaBlock := style8d.ResolvePersonaBlock(persona.Persona, persona.StyleProfile, persona.Brief)

	researchNotes := ""
	if req.UseWebSearch {
		research, rerr := l.svcCtx.Placement.ResearchSettings(l.ctx, tenantID, uid)
		if rerr == nil && placement.WebSearchAvailable(research) {
			memberCtx, merr := l.svcCtx.ThreadsAccount.ResolveMemberPlacementContext(l.ctx, tenantID, uid, research)
			if merr == nil {
				webClient := websearch.New(memberCtx.WebSearchConfig())
				if webClient.Enabled() {
					resp, _ := webClient.Search(l.ctx, websearch.SearchOptions{
						Query: topic + " " + strings.TrimSpace(req.Brief),
						Limit: 5,
						Mode:  websearch.ModeKnowledgeExpand,
					})
					if len(resp.Results) > 0 {
						var b strings.Builder
						for _, snip := range resp.Results {
							if snip.Title != "" {
								b.WriteString("- ")
								b.WriteString(snip.Title)
								b.WriteString("\n")
							}
							if snip.Snippet != "" {
								b.WriteString(snip.Snippet)
								b.WriteString("\n")
							}
						}
						researchNotes = strings.TrimSpace(b.String())
					}
				}
			}
		}
	}

	list := make([]types.CopyDraftData, 0, count)
	for i := 0; i < count; i++ {
		generated, genErr := libformula.GenerateDraft(l.ctx, l.svcCtx.AI, aiReq, libformula.GenerateInput{
			Topic:         topic,
			Brief:         req.Brief,
			PersonaBlock:  personaBlock,
			ResearchNotes: researchNotes,
			Formula:       *formula,
		})
		if genErr != nil {
			return nil, app.For(code.AI).SvcThirdParty("貼文生成失敗：" + genErr.Error())
		}
		saved, saveErr := l.svcCtx.CopyDraft.Create(l.ctx, copydraftdomain.CreateRequest{
			TenantID:       tenantID,
			OwnerUID:       uid,
			PersonaID:      personaID,
			FormulaID:      formula.ID,
			DraftType:      copydraftentity.DraftTypeFormula,
			Text:           generated.Text,
			TopicTag:       generated.TopicTag,
			Angle:          generated.Angle,
			Hook:           generated.Hook,
			Rationale:      generated.Rationale,
			ReferenceNotes: generated.StructureNotes,
			Sources:        []string{formula.Label},
		})
		if saveErr != nil {
			return nil, saveErr
		}
		list = append(list, toCopyDraftData(*saved))
	}
	return &types.GenerateFromContentFormulaData{
		List:    list,
		Message: fmt.Sprintf("已產生 %d 篇可編輯草稿，已加入排程區", len(list)),
	}, nil
}
