package placement_topic

import (
	brandentity "haixun-backend/internal/model/brand/domain/entity"
	kgusecase "haixun-backend/internal/model/knowledge_graph/domain/usecase"
	outreachusecase "haixun-backend/internal/model/outreach_draft/domain/usecase"
	domusecase "haixun-backend/internal/model/placement_topic/domain/usecase"
	scanpostusecase "haixun-backend/internal/model/scan_post/domain/usecase"
	"haixun-backend/internal/types"
)

func toPlacementTopicData(item domusecase.TopicSummary) types.PlacementTopicData {
	return types.PlacementTopicData{
		ID:               item.ID,
		BrandID:          item.BrandID,
		BrandDisplayName: item.BrandDisplayName,
		TopicName:        item.TopicName,
		SeedQuery:        item.SeedQuery,
		Brief:            item.Brief,
		ProductID:        item.ProductID,
		ResearchMap:      toResearchMapData(item.ResearchMap),
		CreateAt:         item.CreateAt,
		UpdateAt:         item.UpdateAt,
	}
}

func toListData(result *domusecase.ListResult) *types.ListPlacementTopicsData {
	if result == nil {
		return &types.ListPlacementTopicsData{List: []types.PlacementTopicData{}}
	}
	list := make([]types.PlacementTopicData, 0, len(result.List))
	for _, item := range result.List {
		list = append(list, toPlacementTopicData(item))
	}
	return &types.ListPlacementTopicsData{List: list}
}

func toResearchMapData(item brandentity.ResearchMap) types.ResearchMapData {
	items := make([]types.ResearchItemData, 0, len(item.ResearchItems))
	for _, researchItem := range item.ResearchItems {
		items = append(items, types.ResearchItemData{
			Title:   researchItem.Title,
			URL:     researchItem.URL,
			Snippet: researchItem.Snippet,
			Query:   researchItem.Query,
		})
	}
	return types.ResearchMapData{
		AudienceSummary: item.AudienceSummary,
		ContentGoal:     item.ContentGoal,
		Questions:       item.Questions,
		Pillars:         item.Pillars,
		Exclusions:      item.Exclusions,
		ResearchItems:   items,
		ExpandStrategy:  item.ExpandStrategy,
		PatrolKeywords:  append([]string(nil), item.PatrolKeywords...),
	}
}

func toTopicPatch(req *types.UpdatePlacementTopicReq) domusecase.TopicPatch {
	if req == nil {
		return domusecase.TopicPatch{}
	}
	patch := domusecase.TopicPatch{
		BrandID:   req.BrandID,
		TopicName: req.TopicName,
		SeedQuery: req.SeedQuery,
		Brief:     req.Brief,
		ProductID: req.ProductID,
	}
	if req.AudienceSummary != nil {
		patch.AudienceSummary = req.AudienceSummary
	}
	if req.ContentGoal != nil {
		patch.ContentGoal = req.ContentGoal
	}
	if req.Questions != nil {
		patch.QuestionsSet = true
		patch.Questions = append([]string(nil), req.Questions...)
	}
	if req.Pillars != nil {
		patch.PillarsSet = true
		patch.Pillars = append([]string(nil), req.Pillars...)
	}
	if req.Exclusions != nil {
		patch.ExclusionsSet = true
		patch.Exclusions = append([]string(nil), req.Exclusions...)
	}
	if req.PatrolKeywords != nil {
		patch.PatrolKeywordsSet = true
		patch.PatrolKeywords = append([]string(nil), req.PatrolKeywords...)
	}
	return patch
}

func toKnowledgeGraphData(graph *kgusecase.GraphSummary) types.KnowledgeGraphData {
	if graph == nil {
		return types.KnowledgeGraphData{}
	}
	nodes := make([]types.KnowledgeGraphNodeData, 0, len(graph.Nodes))
	for _, node := range graph.Nodes {
		evidence := make([]types.KnowledgeGraphEvidenceData, 0, len(node.Evidence))
		for _, item := range node.Evidence {
			evidence = append(evidence, types.KnowledgeGraphEvidenceData{
				URL:     item.URL,
				Snippet: item.Snippet,
				Query:   item.Query,
			})
		}
		nodes = append(nodes, types.KnowledgeGraphNodeData{
			ID:              node.ID,
			Label:           node.Label,
			NodeKind:        node.NodeKind,
			Type:            node.Type,
			Layer:           node.Layer,
			Relation:        node.Relation,
			PlacementValue:  node.PlacementValue,
			ProductFitScore: node.ProductFitScore,
			SelectedForScan: node.SelectedForScan,
			RelevanceTags:   append([]string{}, node.DerivedTags.Relevance...),
			RecencyTags:     append([]string{}, node.DerivedTags.Recency...),
			Evidence:        evidence,
		})
	}
	edges := make([]types.KnowledgeGraphEdgeData, 0, len(graph.Edges))
	for _, edge := range graph.Edges {
		edges = append(edges, types.KnowledgeGraphEdgeData{
			From:     edge.From,
			To:       edge.To,
			Relation: edge.Relation,
		})
	}
	sources := make([]types.BraveSourceData, 0, len(graph.BraveSources))
	for _, src := range graph.BraveSources {
		sources = append(sources, types.BraveSourceData{
			Query:   src.Query,
			Title:   src.Title,
			URL:     src.URL,
			Snippet: src.Snippet,
		})
	}
	return types.KnowledgeGraphData{
		ID:             graph.ID,
		BrandID:        graph.BrandID,
		Seed:           graph.Seed,
		Nodes:          nodes,
		Edges:          edges,
		BraveSources:   sources,
		ExpandStrategy: graph.ExpandStrategy,
		PainTagCount:   graph.PainTagCount,
		GeneratedAt:    graph.GeneratedAt,
		CreateAt:       graph.CreateAt,
		UpdateAt:       graph.UpdateAt,
	}
}

func toScanPostData(post *scanpostusecase.ScanPostSummary) *types.ScanPostData {
	if post == nil {
		return nil
	}
	return &types.ScanPostData{
		ID:                 post.ID,
		GraphNodeID:        post.GraphNodeID,
		SearchTag:          post.SearchTag,
		QueryDimension:     post.QueryDimension,
		ExternalID:         post.ExternalID,
		Permalink:          post.Permalink,
		Author:             post.Author,
		Text:               post.Text,
		Priority:           post.Priority,
		PlacementScore:     post.PlacementScore,
		ProductFitScore:    post.ProductFitScore,
		SolvedByProduct:    post.SolvedByProduct,
		Source:             post.Source,
		ScanJobID:          post.ScanJobID,
		OutreachStatus:     post.OutreachStatus,
		PublishedReplyID:   post.PublishedReplyID,
		PublishedPermalink: post.PublishedPermalink,
		OutreachUpdateAt:   post.OutreachUpdateAt,
		PostedAt:           post.PostedAt,
		Replies:            toScanReplyData(post.Replies),
		CreateAt:           post.CreateAt,
	}
}

func toScanReplyData(replies []scanpostusecase.ScanReplySummary) []types.ScanReplyData {
	if len(replies) == 0 {
		return nil
	}
	out := make([]types.ScanReplyData, 0, len(replies))
	for _, reply := range replies {
		out = append(out, types.ScanReplyData{
			ExternalID: reply.ExternalID,
			Author:     reply.Author,
			Text:       reply.Text,
			Permalink:  reply.Permalink,
			LikeCount:  reply.LikeCount,
			PostedAt:   reply.PostedAt,
		})
	}
	return out
}

func toOutreachDraftData(saved *outreachusecase.DraftSummary) *types.GenerateOutreachDraftsData {
	if saved == nil {
		return nil
	}
	drafts := make([]types.OutreachDraftItemData, 0, len(saved.Drafts))
	for _, item := range saved.Drafts {
		drafts = append(drafts, types.OutreachDraftItemData{
			Text:      item.Text,
			Angle:     item.Angle,
			Rationale: item.Rationale,
		})
	}
	return &types.GenerateOutreachDraftsData{
		ID:         saved.ID,
		ScanPostID: saved.ScanPostID,
		Relevance:  saved.Relevance,
		Reason:     saved.Reason,
		Drafts:     drafts,
		CreateAt:   saved.CreateAt,
	}
}
