package activity

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/service/content"
	activity "github.com/tidbcloud/AgentTeam/internal/store/resource/activity"
	"github.com/tidbcloud/AgentTeam/internal/store/resource/repos"
)

type ContentVersionActivityReader interface {
	GetContent(context.Context, string, string) (content.Content, error)
	GetVersion(context.Context, string, string, string) (content.Version, error)
}

// ContentVersionActivityConsumer projects native immutable-version commits
// into the existing idempotent resource activity stream.
type ContentVersionActivityConsumer struct {
	content  ContentVersionActivityReader
	activity *activity.Store
}

func NewContentVersionActivityConsumer(content ContentVersionActivityReader, activityStore *activity.Store) (*ContentVersionActivityConsumer, error) {
	if content == nil || activityStore == nil {
		return nil, fmt.Errorf("content version activity dependencies are required")
	}
	return &ContentVersionActivityConsumer{content: content, activity: activityStore}, nil
}

func (consumer *ContentVersionActivityConsumer) ConsumeVersionCommitted(ctx context.Context, event content.VersionCommittedEvent) error {
	if consumer == nil || consumer.content == nil || consumer.activity == nil {
		return fmt.Errorf("content version activity consumer is not configured")
	}
	if strings.TrimSpace(event.ID) == "" || strings.TrimSpace(event.WorkspaceID) == "" || strings.TrimSpace(event.ContentID) == "" || strings.TrimSpace(event.VersionID) == "" {
		return fmt.Errorf("content version activity event identity is invalid")
	}
	content, err := consumer.content.GetContent(ctx, event.WorkspaceID, event.ContentID)
	if err != nil {
		return fmt.Errorf("load content version activity lineage: %w", err)
	}
	version, err := consumer.content.GetVersion(ctx, event.WorkspaceID, event.ContentID, event.VersionID)
	if err != nil {
		return fmt.Errorf("load content version activity version: %w", err)
	}
	assetType, ok := contentActivityAssetType(content.Domain)
	if !ok {
		return nil
	}
	actorType := ActivityActorTypeUser
	if strings.HasPrefix(version.CreatedBy, strings.TrimSpace(content.Domain)+":") {
		actorType = ActivityActorTypeSystem
	}
	return WriteResourceActivityEvent(ctx, consumer.activity, ResourceActivityEventInput{
		WorkspaceID: event.WorkspaceID, AssetType: assetType, AssetID: contentActivityAssetID(content.Domain, content.BindingKey),
		EventType: activity.EventTypeCommit, ActorType: actorType, ActorID: version.CreatedBy,
		Details: map[string]any{
			"contentId": content.ID, "contentVersionId": version.ID, "model": version.Model,
			"rootDigest": version.RootDigest, "sizeBytes": version.SizeBytes, "fileCount": version.FileCount,
		},
		TargetKind: "content_version", TargetID: version.ID,
		Source: activity.SourceContentStore, SourceEventID: event.ID, OccurredAt: version.CreatedAt,
	})
}

func contentActivityAssetID(domain, bindingKey string) string {
	bindingKey = strings.TrimSpace(bindingKey)
	if strings.TrimSpace(domain) == "automation" {
		return repos.AutomationRepositoryResourceID(bindingKey)
	}
	if len(bindingKey) <= 64 {
		return bindingKey
	}
	digest := sha256.Sum256([]byte(strings.ToLower(bindingKey)))
	return hex.EncodeToString(digest[:])
}

func contentActivityAssetType(domain string) (string, bool) {
	switch strings.TrimSpace(domain) {
	case "memory":
		return activity.AssetTypeMemory, true
	case "skill":
		return activity.AssetTypeSkill, true
	case "kb", "kb_source", "knowledge_base":
		return activity.AssetTypeKB, true
	case "role":
		return activity.AssetTypeRole, true
	case "automation":
		return activity.AssetTypeAutomation, true
	default:
		return "", false
	}
}
