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

package persona

import (
	"context"
	"fmt"

	"haixun-backend/internal/library/publishschedule"
	copydraftdomain "haixun-backend/internal/model/copy_draft/domain/usecase"
	pqdomain "haixun-backend/internal/model/publish_queue/domain/usecase"
	"haixun-backend/internal/svc"
	"haixun-backend/internal/types"

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

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

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

func (l *SchedulePersonaDraftsLogic) SchedulePersonaDrafts(req *types.SchedulePersonaDraftsHandlerReq) (resp *types.ScheduleCopyDraftsData, err error) {
	tenantID, uid, err := actorFrom(l.ctx)
	if err != nil {
		return nil, err
	}
	if _, err := l.svcCtx.Persona.Get(l.ctx, tenantID, uid, req.ID); err != nil {
		return nil, err
	}
	if _, err := l.svcCtx.ThreadsAccount.Get(l.ctx, tenantID, uid, req.AccountID); err != nil {
		return nil, err
	}
	times := scheduleTimes(req.StartAt, req.Timezone, req.Slots, len(req.DraftIDs))
	list := make([]types.PublishQueueItemData, 0, len(req.DraftIDs))
	for idx, draftID := range req.DraftIDs {
		draft, err := l.svcCtx.CopyDraft.Get(l.ctx, tenantID, uid, req.ID, draftID)
		if err != nil {
			return nil, err
		}
		if draft.PublishQueueID != "" {
			queueItems, err := l.svcCtx.PublishQueue.ListByIDs(l.ctx, tenantID, uid, []string{draft.PublishQueueID})
			if err != nil {
				return nil, err
			}
			if len(queueItems) > 0 {
				list = append(list, publishQueueData(&queueItems[0]))
				continue
			}
		}
		scheduledAt := int64(0)
		if idx < len(times) {
			scheduledAt = times[idx]
		}
		item, err := l.svcCtx.PublishQueue.Create(l.ctx, pqdomain.CreateRequest{
			TenantID: tenantID, OwnerUID: uid, AccountID: req.AccountID,
			PersonaID: req.ID, CopyMissionID: draft.CopyMissionID, CopyDraftID: draft.ID,
			Text: draft.Text, TopicTag: draft.TopicTag, ScheduledAt: scheduledAt,
		})
		if err != nil {
			return nil, err
		}
		if _, err := l.svcCtx.CopyDraft.MarkScheduled(l.ctx, copydraftdomain.MarkScheduledRequest{
			TenantID: tenantID, OwnerUID: uid, PersonaID: req.ID, DraftID: draft.ID, QueueID: item.ID,
		}); err != nil {
			_ = l.svcCtx.PublishQueue.Delete(l.ctx, tenantID, uid, req.AccountID, item.ID)
			return nil, err
		}
		list = append(list, publishQueueData(item))
	}
	return &types.ScheduleCopyDraftsData{
		Scheduled: len(list), List: list, Message: fmt.Sprintf("已排程 %d 篇草稿", len(list)),
	}, nil
}

func scheduleTimes(startAt int64, timezone string, slots []types.PublishSlotData, count int) []int64 {
	converted := make([]publishschedule.Slot, 0, len(slots))
	for _, slot := range slots {
		converted = append(converted, publishschedule.Slot{Weekday: slot.Weekday, Time: slot.Time})
	}
	return publishschedule.BuildSchedule(startAt, timezone, converted, count)
}

func publishQueueData(item *pqdomain.QueueItemSummary) types.PublishQueueItemData {
	if item == nil {
		return types.PublishQueueItemData{}
	}
	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,
	}
}
