package threads_account

import (
	guarddomain "haixun-backend/internal/model/publish_guard/domain/usecase"
	inventorydomain "haixun-backend/internal/model/publish_inventory/domain/usecase"
	pqdomain "haixun-backend/internal/model/publish_queue/domain/usecase"
	eventdomain "haixun-backend/internal/model/publish_queue_event/domain/usecase"
	domusecase "haixun-backend/internal/model/threads_account/domain/usecase"
	"haixun-backend/internal/types"
)

func toThreadsAccountData(item domusecase.AccountSummary) types.ThreadsAccountData {
	return types.ThreadsAccountData{
		ID:                item.ID,
		DisplayName:       item.DisplayName,
		Username:          item.Username,
		ThreadsUserID:     item.ThreadsUserID,
		PersonaID:         item.PersonaID,
		BrowserConnected:  item.BrowserConnected,
		ApiConnected:      item.ApiConnected,
		APITokenExpiresAt: item.APITokenExpiresAt,
		Status:            item.Status,
		CreateAt:          item.CreateAt,
		UpdateAt:          item.UpdateAt,
	}
}

func toPostPerformanceData(result *domusecase.PostPerformanceResult) *types.ThreadsPostPerformanceData {
	if result == nil {
		return &types.ThreadsPostPerformanceData{Posts: []types.ThreadsPostPerformanceItem{}}
	}
	caps := make([]types.ThreadsPostMetricCapability, 0, len(result.Capabilities))
	for _, item := range result.Capabilities {
		caps = append(caps, types.ThreadsPostMetricCapability{
			Scope: item.Scope, Name: item.Name, Metrics: item.Metrics,
			Trackable: item.Trackable, Note: item.Note,
		})
	}
	metrics := make([]types.ThreadsInsightMetricItem, 0, len(result.AccountInsights.Metrics))
	for _, item := range result.AccountInsights.Metrics {
		metrics = append(metrics, types.ThreadsInsightMetricItem{Name: item.Name, Value: item.Value})
	}
	posts := make([]types.ThreadsPostPerformanceItem, 0, len(result.Posts))
	for _, item := range result.Posts {
		posts = append(posts, types.ThreadsPostPerformanceItem{
			MediaID: item.MediaID, Text: item.Text, Permalink: item.Permalink, Timestamp: item.Timestamp,
			MediaType: item.MediaType, MediaURL: item.MediaURL, ThumbnailURL: item.ThumbnailURL,
			TopicTag: item.TopicTag, Shortcode: item.Shortcode,
			LikeCount: item.LikeCount, ReplyCount: item.ReplyCount, RepostCount: item.RepostCount, QuoteCount: item.QuoteCount,
			Views: item.Views, Shares: item.Shares, InsightsStatus: item.InsightsStatus, InsightsMessage: item.InsightsMessage,
		})
	}
	return &types.ThreadsPostPerformanceData{
		AccountID: result.AccountID, Username: result.Username, ThreadsUserID: result.ThreadsUserID,
		FetchedAt: result.FetchedAt, Capabilities: caps,
		AccountInsights: types.ThreadsAccountInsightsBlock{
			Status: result.AccountInsights.Status, Message: result.AccountInsights.Message, Metrics: metrics,
		},
		Posts: posts,
	}
}

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

func toConnectionData(data *domusecase.ConnectionData) *types.ThreadsAccountConnectionData {
	if data == nil {
		return nil
	}
	return &types.ThreadsAccountConnectionData{
		AccountID:        data.AccountID,
		AccountName:      data.AccountName,
		Username:         data.Username,
		BrowserConnected: data.BrowserConnected,
		ApiConnected:     data.ApiConnected,
		Prefs: types.ThreadsAccountConnectionPrefs{
			SearchViaApi:     data.Prefs.SearchViaApi,
			SearchSourceMode: data.Prefs.SearchSourceMode,
			PublishViaApi:    data.Prefs.PublishViaApi,
			DevMode:          data.Prefs.DevMode,
			ScrapeReplies:    data.Prefs.ScrapeReplies,
			RepliesPerPost:   data.Prefs.RepliesPerPost,
			PublishHeaded:    data.Prefs.PublishHeaded,
			PlaywrightDebug:  data.Prefs.PlaywrightDebug,
		},
	}
}

func toPublishQueueItemData(item *pqdomain.QueueItemSummary) *types.PublishQueueItemData {
	if item == nil {
		return nil
	}
	return &types.PublishQueueItemData{
		ID:            item.ID,
		AccountID:     item.AccountID,
		PersonaID:     item.PersonaID,
		CopyMissionID: item.CopyMissionID,
		CopyDraftID:   item.CopyDraftID,
		Text:          item.Text,
		TopicTag:      item.TopicTag,
		ScheduledAt:   item.ScheduledAt,
		Status:        item.Status,
		MediaID:       item.MediaID,
		Permalink:     item.Permalink,
		PublishedAt:   item.PublishedAt,
		ErrorMessage:  item.ErrorMessage,
		RetryCount:    item.RetryCount,
		LastAttemptAt: item.LastAttemptAt,
		NextAttemptAt: item.NextAttemptAt,
		MissedAt:      item.MissedAt,
		PausedReason:  item.PausedReason,
		CreateAt:      item.CreateAt,
		UpdateAt:      item.UpdateAt,
	}
}

func toInventoryPolicyData(item *inventorydomain.PolicySummary) *types.PublishInventoryPolicyData {
	if item == nil {
		return nil
	}
	slots := make([]types.PublishSlotData, 0, len(item.Slots))
	for _, slot := range item.Slots {
		slots = append(slots, types.PublishSlotData{Weekday: slot.Weekday, Time: slot.Time})
	}
	refs := make([]types.PublishSourceRefData, 0, len(item.SourceRefs))
	for _, ref := range item.SourceRefs {
		refs = append(refs, types.PublishSourceRefData{
			Type: ref.Type, PersonaID: ref.PersonaID, CopyMissionID: ref.CopyMissionID, ScanPostID: ref.ScanPostID, ManualSeed: ref.ManualSeed,
		})
	}
	return &types.PublishInventoryPolicyData{
		AccountID: item.AccountID, Enabled: item.Enabled, TargetDailyCount: item.TargetDailyCount,
		LowStockThreshold: item.LowStockThreshold, LookaheadDays: item.LookaheadDays,
		Timezone: item.Timezone, Slots: slots, SourceRefs: refs, UpdateAt: item.UpdateAt,
	}
}

func toGuardPolicyData(item *guarddomain.PolicySummary) *types.PublishGuardPolicyData {
	if item == nil {
		return nil
	}
	return &types.PublishGuardPolicyData{
		AccountID: item.AccountID, Enabled: item.Enabled, MaxDailyPosts: item.MaxDailyPosts,
		MinIntervalMinutes: item.MinIntervalMinutes, ConsecutiveFailurePauseLimit: item.ConsecutiveFailurePauseLimit,
		Paused: item.Paused, PausedReason: item.PausedReason, UpdateAt: item.UpdateAt,
	}
}

func toQueueEventData(items []eventdomain.EventSummary) []types.PublishQueueEventData {
	out := make([]types.PublishQueueEventData, 0, len(items))
	for _, item := range items {
		out = append(out, types.PublishQueueEventData{
			ID: item.ID, QueueID: item.QueueID, EventType: item.EventType,
			FromStatus: item.FromStatus, ToStatus: item.ToStatus, Message: item.Message, CreateAt: item.CreateAt,
		})
	}
	return out
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if value != "" {
			return value
		}
	}
	return ""
}

func toPublishQueueListData(result *pqdomain.ListResult) *types.PublishQueueListData {
	if result == nil {
		return &types.PublishQueueListData{List: []types.PublishQueueItemData{}}
	}
	list := make([]types.PublishQueueItemData, 0, len(result.Items))
	for _, item := range result.Items {
		if data := toPublishQueueItemData(&item); data != nil {
			list = append(list, *data)
		}
	}
	return &types.PublishQueueListData{
		Pagination: types.PaginationData{
			Total:      result.Total,
			Page:       int64(result.Page),
			PageSize:   int64(result.PageSize),
			TotalPages: int64(result.TotalPages),
		},
		List: list,
	}
}

func toPublishHealthData(result *pqdomain.PublishHealthResult) *types.ThreadsPublishHealthData {
	if result == nil {
		return &types.ThreadsPublishHealthData{List: []types.ThreadsPublishHealthItem{}}
	}
	list := make([]types.ThreadsPublishHealthItem, 0, len(result.Items))
	for _, item := range result.Items {
		cps := make([]types.ThreadsPublishHealthCheckpoint, 0, len(item.Checkpoints))
		for _, cp := range item.Checkpoints {
			cps = append(cps, types.ThreadsPublishHealthCheckpoint{
				Checkpoint: cp.Checkpoint, LikeCount: cp.LikeCount, ReplyCount: cp.ReplyCount,
				RepostCount: cp.RepostCount, QuoteCount: cp.QuoteCount, Views: cp.Views, CheckedAt: cp.CheckedAt,
			})
		}
		list = append(list, types.ThreadsPublishHealthItem{
			MediaID: item.MediaID, Permalink: item.Permalink, Text: item.Text,
			PublishedAt: item.PublishedAt, LikeCount: item.LikeCount, ReplyCount: item.ReplyCount,
			RepostCount: item.RepostCount, QuoteCount: item.QuoteCount,
			Views: item.Views, Shares: item.Shares, Checkpoints: cps,
		})
	}
	return &types.ThreadsPublishHealthData{
		Summary: types.ThreadsPublishHealthSummary{
			PendingScheduled: result.Summary.PendingScheduled,
			FailedCount:      result.Summary.FailedCount,
			Published7d:      result.Summary.Published7d,
			TotalLikes7d:     result.Summary.TotalLikes7d,
			TotalReplies7d:   result.Summary.TotalReplies7d,
		},
		Pagination: types.PaginationData{
			Total: result.Total, Page: int64(result.Page), PageSize: int64(result.PageSize), TotalPages: int64(result.TotalPages),
		},
		List: list,
	}
}

func toConnectionPatch(req *types.UpdateThreadsAccountConnectionReq) domusecase.ConnectionPrefsPatch {
	if req == nil {
		return domusecase.ConnectionPrefsPatch{}
	}
	return domusecase.ConnectionPrefsPatch{
		SearchViaApi:     req.SearchViaApi,
		SearchSourceMode: req.SearchSourceMode,
		PublishViaApi:    req.PublishViaApi,
		DevMode:          req.DevMode,
		ScrapeReplies:    req.ScrapeReplies,
		RepliesPerPost:   req.RepliesPerPost,
		PublishHeaded:    req.PublishHeaded,
		PlaywrightDebug:  req.PlaywrightDebug,
	}
}
