package personacopy

import (
	"context"
	"fmt"
	"strings"

	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"
	contentformuladomain "haixun-backend/internal/model/content_formula/domain/usecase"
	copydraftentity "haixun-backend/internal/model/copy_draft/domain/entity"
	copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase"
	personadomain "haixun-backend/internal/model/persona/domain/usecase"
	placementusecase "haixun-backend/internal/model/placement/usecase"
	threadsaccountdomain "haixun-backend/internal/model/threads_account/domain/usecase"
)

type FormulaDraftInput struct {
	TenantID     string
	OwnerUID     string
	PersonaID    string
	AccountID    string
	FormulaID    string
	Topic        string
	Brief        string
	UseWebSearch bool
	DraftCount   int
}

type FormulaDraftDeps struct {
	Persona        personadomain.UseCase
	ContentFormula contentformuladomain.UseCase
	CopyDraft      copydraftdomain.UseCase
	ThreadsAccount threadsaccountdomain.UseCase
	Placement      placementusecase.UseCase
	AI             domai.UseCase
}

func RunFormulaDraft(ctx context.Context, deps FormulaDraftDeps, in FormulaDraftInput, progress ProgressFn) (int, error) {
	if progress == nil {
		progress = func(string, int) {}
	}
	topic := strings.TrimSpace(in.Topic)
	if topic == "" {
		return 0, fmt.Errorf("topic is required")
	}
	count := in.DraftCount
	if count <= 0 {
		count = 1
	}
	if count > 5 {
		count = 5
	}

	progress("讀取人設與寫法公式…", 10)
	persona, err := deps.Persona.Get(ctx, in.TenantID, in.OwnerUID, in.PersonaID)
	if err != nil {
		return 0, err
	}
	if !style8d.HasReady8D(persona.Persona, persona.StyleProfile) {
		return 0, fmt.Errorf("請先完成人設 8D 對標分析")
	}
	formula, err := deps.ContentFormula.Get(ctx, in.TenantID, in.OwnerUID, in.AccountID, in.FormulaID)
	if err != nil {
		return 0, err
	}
	credential, err := deps.ThreadsAccount.ResolveMemberAiCredential(ctx, in.TenantID, in.OwnerUID)
	if err != nil {
		return 0, err
	}
	providerID, err := aiusecase.MapWorkerProvider(credential.Provider)
	if err != nil {
		return 0, 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 in.UseWebSearch {
		progress("搜尋網路參考資料…", 20)
		researchNotes = searchFormulaNotes(ctx, deps, in.TenantID, in.OwnerUID, topic, in.Brief)
	}

	created := 0
	for i := 0; i < count; i++ {
		progress(fmt.Sprintf("呼叫 AI 產生草稿 %d/%d（%s / %s）…", i+1, count, credential.Provider, credential.Model), 35+(i*40/count))
		generated, genErr := libformula.GenerateDraft(ctx, deps.AI, aiReq, libformula.GenerateInput{
			Topic:         topic,
			Brief:         in.Brief,
			PersonaBlock:  personaBlock,
			ResearchNotes: researchNotes,
			Formula:       *formula,
		})
		if genErr != nil {
			return created, genErr
		}
		if _, saveErr := deps.CopyDraft.Create(ctx, copydraftdomain.CreateRequest{
			TenantID:       in.TenantID,
			OwnerUID:       in.OwnerUID,
			PersonaID:      in.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},
		}); saveErr != nil {
			return created, saveErr
		}
		created++
	}
	progress(fmt.Sprintf("已產生 %d 篇草稿", created), 100)
	return created, nil
}

func searchFormulaNotes(ctx context.Context, deps FormulaDraftDeps, tenantID, uid, topic, brief string) string {
	research, err := deps.Placement.ResearchSettings(ctx, tenantID, uid)
	if err != nil || !placement.WebSearchAvailable(research) {
		return ""
	}
	memberCtx, err := deps.ThreadsAccount.ResolveMemberPlacementContext(ctx, tenantID, uid, research)
	if err != nil {
		return ""
	}
	webClient := websearch.New(memberCtx.WebSearchConfig())
	if !webClient.Enabled() {
		return ""
	}
	resp, err := webClient.Search(ctx, websearch.SearchOptions{
		Query: topic + " " + strings.TrimSpace(brief),
		Limit: 5,
		Mode:  websearch.ModeKnowledgeExpand,
	})
	if err != nil || len(resp.Results) == 0 {
		return ""
	}
	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")
		}
	}
	return strings.TrimSpace(b.String())
}
