// Package ports defines the interfaces (hexagonal "ports") that the use-case
// engine depends on. Concrete adapters live in internal/adapters. The engine
// imports this package; it never imports a concrete provider, store, or model.
// See docs/architecture/architecture.md.
package ports

import (
	"context"

	"git.d-ma.be/mathias/tapir/internal/domain"
)

// VideoSource is a video platform Tapir watches (YouTube, Vimeo).
type VideoSource interface {
	// ListSubscriptions returns the channels the user subscribes to.
	ListSubscriptions(ctx context.Context, userID string) ([]domain.Subscription, error)
	// NewVideos returns videos newly seen for the given subscription.
	NewVideos(ctx context.Context, sub domain.Subscription) ([]domain.Video, error)
	// FetchTranscript resolves a transcript, captions-first. Returns a
	// Transcript with Source == SourceNone when none is available (not an error).
	FetchTranscript(ctx context.Context, v domain.Video) (domain.Transcript, error)
}

// Summarizer turns a transcript into a summary. Backed by the AI router
// (local Primary -> BYO Fallback). See docs/use-cases/ai_routing.feature.
type Summarizer interface {
	Summarize(ctx context.Context, v domain.Video, t domain.Transcript) (domain.Summary, error)
}

// TranscriptStore persists transcripts as shared, video-keyed public content
// (ADR-021). It is keyed by the cross-user dedup key (provider, providerVideoID)
// — the video's public identity, NOT Tapir's per-user videos.id — and holds only
// public caption content, so it is deliberately NOT user-scoped: two users who
// share a video share the one row. The engine reads it before any caption fetch
// so re-analysis never re-touches YouTube (ADR-010/014).
type TranscriptStore interface {
	// GetTranscript returns the stored transcript for a video and whether one
	// exists. A stored Source == SourceNone (captions permanently absent) is a
	// real hit: ok is true and HasText() is false, so callers skip without
	// re-fetching. A transient rate-limit is never stored, so it never appears
	// here as a false absence.
	GetTranscript(ctx context.Context, provider, providerVideoID string) (t domain.Transcript, ok bool, err error)
	// SaveTranscript upserts the transcript for (provider, providerVideoID). Only
	// terminal outcomes are persisted: SourceCaptions (with text) or SourceNone.
	// SourceRateLimited must NOT be passed — it is a per-user retry (ADR-014), not
	// a shared terminal state.
	SaveTranscript(ctx context.Context, provider, providerVideoID string, t domain.Transcript) error
}

// Sink delivers a summary to a destination (user store, brain, ...).
// Implementations fail independently of one another.
type Sink interface {
	// Name identifies the sink for delivery records ("store", "brain").
	Name() string
	Deliver(ctx context.Context, s domain.Summary) error
}

// SecretStore resolves opaque references to secret material (OAuth tokens,
// BYO keys). Backed by ESO/1Password. Tables store only the reference.
type SecretStore interface {
	Get(ctx context.Context, ref string) (string, error)
}
