package usecase

import (
	"context"
	"strings"

	"haixun-backend/internal/library/clock"
	"haixun-backend/internal/library/placement"
	libviral "haixun-backend/internal/library/viral"
	accountentity "haixun-backend/internal/model/threads_account/domain/entity"
	domusecase "haixun-backend/internal/model/threads_account/domain/usecase"
)

func (u *threadsAccountUseCase) GetKnownAccounts(
	ctx context.Context,
	tenantID, ownerUID, accountID string,
) (map[string]accountentity.KnownAccountProfile, error) {
	if err := requireActor(tenantID, ownerUID); err != nil {
		return nil, err
	}
	accountID = strings.TrimSpace(accountID)
	if accountID == "" {
		return map[string]accountentity.KnownAccountProfile{}, nil
	}
	account, err := u.assertOwned(ctx, tenantID, ownerUID, accountID)
	if err != nil {
		return nil, err
	}
	return cloneKnownAccounts(account.KnownAccounts), nil
}

func (u *threadsAccountUseCase) UpsertKnownAccountsFromScan(
	ctx context.Context,
	req domusecase.UpsertKnownAccountsFromScanRequest,
) error {
	if err := requireActor(req.TenantID, req.OwnerUID); err != nil {
		return err
	}
	accountID := strings.TrimSpace(req.AccountID)
	if accountID == "" || len(req.SimilarAccounts) == 0 {
		return nil
	}
	account, err := u.assertOwned(ctx, req.TenantID, req.OwnerUID, accountID)
	if err != nil {
		return err
	}
	now := clock.NowUnixNano()
	merged := libviral.MergeKnownAccountsFromScan(
		cloneKnownAccounts(account.KnownAccounts),
		req.SimilarAccounts,
		strings.TrimSpace(req.MissionID),
		strings.TrimSpace(req.PersonaID),
		req.SelectedTags,
		now,
	)
	return u.repo.SetKnownAccounts(ctx, req.TenantID, req.OwnerUID, accountID, merged)
}

func (u *threadsAccountUseCase) ResolveMemberCapabilities(
	ctx context.Context,
	tenantID, ownerUID string,
	research placement.ResearchSettings,
) (placement.MemberCapabilities, error) {
	if err := requireActor(tenantID, ownerUID); err != nil {
		return placement.MemberCapabilities{}, err
	}
	member, err := u.ResolveMemberPlacementContext(ctx, tenantID, ownerUID, research)
	if err != nil {
		return placement.MemberCapabilities{}, err
	}
	_, aiErr := u.ResolveMemberAiCredential(ctx, tenantID, ownerUID)
	_, publishErr := u.ResolveMemberThreadsPublishCredential(ctx, tenantID, ownerUID)
	return placement.BuildMemberCapabilities(member, research, aiErr == nil, publishErr == nil), nil
}

func cloneKnownAccounts(in map[string]accountentity.KnownAccountProfile) map[string]accountentity.KnownAccountProfile {
	if len(in) == 0 {
		return map[string]accountentity.KnownAccountProfile{}
	}
	out := make(map[string]accountentity.KnownAccountProfile, len(in))
	for key, item := range in {
		out[key] = accountentity.KnownAccountProfile{
			FirstSeenAt:   item.FirstSeenAt,
			LastSeenAt:    item.LastSeenAt,
			Missions:      append([]string(nil), item.Missions...),
			PersonaIds:    append([]string(nil), item.PersonaIds...),
			Tags:          append([]string(nil), item.Tags...),
			AvgEngagement: item.AvgEngagement,
			SeenCount:     item.SeenCount,
			Status:        item.Status,
		}
	}
	return out
}
