package contentpayload

import (
	"context"
	"fmt"
)

const (
	DefaultDocumentMaxFiles      = 4_096
	DefaultDocumentMaxFileBytes  = int64(16 << 20)
	DefaultDocumentMaxTotalBytes = int64(16 << 20)
	DefaultDocumentMaxIndexBytes = int64(1 << 20)
)

// StageDocumentRequest is always a canonical full snapshot. Delta payloads are
// transport-only and must be expanded by the caller before this boundary.
type StageDocumentRequest struct {
	WorkspaceID string
	ContentID   string
	VersionID   string
	Files       []File
}

type StagedDocument struct {
	PayloadRef ManifestRef
	RootDigest Digest
	SizeBytes  int64
	FileCount  int
	Created    bool
}

// DocumentPayloadBackend persists independently restorable document snapshots.
// It owns payload bytes only; lineage, quotas, and head CAS remain in the
// transactional Content Store.
type DocumentPayloadBackend interface {
	PayloadBackend
	StageDocument(context.Context, StageDocumentRequest) (StagedDocument, error)
}

type documentBackend struct{ TreePayloadBackend }

// NewDocumentBackend reuses the verified content-addressed filesystem engine
// while exposing document-specific full-snapshot limits and operations.
func NewDocumentBackend(tree TreePayloadBackend) (DocumentPayloadBackend, error) {
	if tree == nil {
		return nil, fmt.Errorf("document payload backend requires tree payload storage")
	}
	return &documentBackend{TreePayloadBackend: tree}, nil
}

func (backend *documentBackend) StageDocument(ctx context.Context, request StageDocumentRequest) (StagedDocument, error) {
	staged, err := backend.StageTree(ctx, StageTreeRequest{
		WorkspaceID: request.WorkspaceID,
		ContentID:   request.ContentID,
		VersionID:   request.VersionID,
		Files:       request.Files,
		Limits: Limits{
			MaxFiles:         DefaultDocumentMaxFiles,
			MaxFileBytes:     DefaultDocumentMaxFileBytes,
			MaxTotalBytes:    DefaultDocumentMaxTotalBytes,
			MaxManifestBytes: DefaultDocumentMaxIndexBytes,
		},
	})
	if err != nil {
		return StagedDocument{}, err
	}
	return StagedDocument{
		PayloadRef: staged.ManifestRef,
		RootDigest: staged.RootDigest,
		SizeBytes:  staged.SizeBytes,
		FileCount:  staged.FileCount,
		Created:    staged.Created,
	}, nil
}
