package usecase

import (
	"context"
	"encoding/json"
	"time"

	"haixun-backend/internal/library/placement"
	missionentity "haixun-backend/internal/model/copy_mission/domain/entity"
	"haixun-backend/internal/model/threads_account/domain/entity"
)

type AccountSummary struct {
	ID                string
	DisplayName       string
	Username          string
	ThreadsUserID     string
	PersonaID         string
	BrowserConnected  bool
	ApiConnected      bool
	APITokenExpiresAt int64
	Status            string
	CreateAt          int64
	UpdateAt          int64
}

type TokenRefreshCandidate struct {
	AccountID string
	TenantID  string
	OwnerUID  string
	ExpiresAt int64
}

type ConnectionPrefs struct {
	SearchViaApi     bool
	SearchSourceMode string
	PublishViaApi    bool
	DevMode          bool
	ScrapeReplies    bool
	RepliesPerPost   int
	PublishHeaded    bool
	PlaywrightDebug  bool
}

type ConnectionData struct {
	AccountID        string
	AccountName      string
	Username         string
	BrowserConnected bool
	ApiConnected     bool
	Prefs            ConnectionPrefs
}

type CreateRequest struct {
	TenantID    string
	OwnerUID    string
	DisplayName string
	Activate    bool
}

type UpdateAccountRequest struct {
	TenantID    string
	OwnerUID    string
	AccountID   string
	DisplayName *string
	PersonaID   *string
}

type UpdateConnectionRequest struct {
	TenantID  string
	OwnerUID  string
	AccountID string
	Prefs     ConnectionPrefsPatch
}

type ImportBrowserSessionRequest struct {
	TenantID     string
	OwnerUID     string
	AccountID    string
	StorageState string
}

type ImportBrowserSessionResult struct {
	AccountID string
	Username  string
	Synced    bool
	Valid     bool
	Message   string
	UpdateAt  int64
}

type SecretsData struct {
	AccountID         string
	APIAccessToken    string
	APITokenExpiresAt int64
	UpdateAt          int64
}

type BrowserSessionData struct {
	AccountID    string
	StorageState string
	UpdateAt     int64
}

type AiSettings struct {
	AccountID         string
	Provider          string
	Model             string
	ResearchProvider  string
	ResearchModel     string
	ApiKeys           map[string]string
	ApiKeysConfigured map[string]bool
}

type AiSettingsPatch struct {
	Provider         *string
	Model            *string
	ResearchProvider *string
	ResearchModel    *string
	ApiKeys          map[string]string
}

// WorkerAiCredential carries raw provider settings for internal workers (never expose to clients).
type WorkerAiCredential struct {
	Provider string
	Model    string
	APIKey   string
}

type ThreadsPublishCredential struct {
	AccountID     string
	ThreadsUserID string
	AccessToken   string
}

type ConnectionPrefsPatch struct {
	SearchViaApi     *bool
	SearchSourceMode *string
	PublishViaApi    *bool
	DevMode          *bool
	ScrapeReplies    *bool
	RepliesPerPost   *int
	PublishHeaded    *bool
	PlaywrightDebug  *bool
}

type ListResult struct {
	List            []AccountSummary
	ActiveAccountID string
}

type OAuthStartResult struct {
	AuthorizeURL string
	State        string
	AccountID    string
}

type OAuthCallbackResult struct {
	AccountID     string
	Username      string
	ThreadsUserID string
	RedirectURL   string
}

type OAuthDebugLogEntry struct {
	At        int64
	Level     string
	Stage     string
	AccountID string
	Message   string
}

type APISmokeTestItem struct {
	Scope   string
	Name    string
	Status  string // ok, error, skip, manual
	Message string
	Count   int
}

type APIPlaygroundRequest struct {
	Action        string
	Query         string
	Username      string
	MediaID       string
	ReplyID       string
	ReplyToID     string
	Text          string
	Permalink     string
	HintText      string
	SkipPrime     bool
	LocationQuery string
	Limit         int
	Hide          bool
	SearchType    string
}

type APIPlaygroundResult struct {
	Action  string
	Ok      bool
	Message string
	Data    json.RawMessage
}

type PostMetricCapability struct {
	Scope     string
	Name      string
	Metrics   []string
	Trackable bool
	Note      string
}

type InsightMetricItem struct {
	Name  string
	Value int
}

type AccountInsightsBlock struct {
	Status  string
	Message string
	Metrics []InsightMetricItem
}

type PostPerformanceItem struct {
	MediaID         string
	Text            string
	Permalink       string
	Timestamp       string
	MediaType       string
	MediaURL        string
	ThumbnailURL    string
	TopicTag        string
	Shortcode       string
	LikeCount       int
	ReplyCount      int
	RepostCount     int
	QuoteCount      int
	Views           int
	Shares          int
	InsightsStatus  string
	InsightsMessage string
}

type PostPerformanceResult struct {
	AccountID       string
	Username        string
	ThreadsUserID   string
	FetchedAt       int64
	Capabilities    []PostMetricCapability
	AccountInsights AccountInsightsBlock
	Posts           []PostPerformanceItem
}

type UpsertKnownAccountsFromScanRequest struct {
	TenantID        string
	OwnerUID        string
	AccountID       string
	MissionID       string
	PersonaID       string
	SelectedTags    []string
	SimilarAccounts []missionentity.SimilarAccount
}

type UseCase interface {
	List(ctx context.Context, tenantID, ownerUID string) (*ListResult, error)
	Create(ctx context.Context, req CreateRequest) (*AccountSummary, error)
	Get(ctx context.Context, tenantID, ownerUID, accountID string) (*AccountSummary, error)
	Update(ctx context.Context, req UpdateAccountRequest) (*AccountSummary, error)
	Activate(ctx context.Context, tenantID, ownerUID, accountID string) error
	Delete(ctx context.Context, tenantID, ownerUID, accountID string) error
	GetConnection(ctx context.Context, tenantID, ownerUID, accountID string) (*ConnectionData, error)
	UpdateConnection(ctx context.Context, req UpdateConnectionRequest) (*ConnectionData, error)
	ImportBrowserSession(ctx context.Context, req ImportBrowserSessionRequest) (*ImportBrowserSessionResult, error)
	GetBrowserSession(ctx context.Context, tenantID, ownerUID, accountID string) (*BrowserSessionData, error)
	GetAiSettings(ctx context.Context, tenantID, ownerUID, accountID string) (*AiSettings, error)
	UpdateAiSettings(ctx context.Context, tenantID, ownerUID, accountID string, patch AiSettingsPatch) (*AiSettings, error)
	ResolveAiProviderAPIKey(ctx context.Context, tenantID, ownerUID, accountID, provider, overrideKey string) (string, error)
	ResolveWorkerAiCredential(ctx context.Context, tenantID, ownerUID, accountID string) (*WorkerAiCredential, error)
	ResolveMemberAiCredential(ctx context.Context, tenantID, ownerUID string) (*WorkerAiCredential, error)
	ResolveMemberResearchAiCredential(ctx context.Context, tenantID, ownerUID string) (*WorkerAiCredential, error)
	ResolveMemberPlacementContext(ctx context.Context, tenantID, ownerUID string, research placement.ResearchSettings) (placement.MemberContext, error)
	ResolveMemberThreadsPublishCredential(ctx context.Context, tenantID, ownerUID string) (*ThreadsPublishCredential, error)
	ResolveMemberThreadsReplyCredential(ctx context.Context, tenantID, ownerUID string) (*ThreadsPublishCredential, error)
	SaveAPIAccessToken(ctx context.Context, accountID, accessToken string, expiresAt int64) (*SecretsData, error)
	StartThreadsOAuth(ctx context.Context, tenantID, ownerUID, accountID string) (*OAuthStartResult, error)
	CompleteThreadsOAuthCallback(ctx context.Context, code, state string) (*OAuthCallbackResult, error)
	DisconnectThreadsAPI(ctx context.Context, tenantID, ownerUID, accountID string) (*AccountSummary, error)
	ListOAuthDebugLogs(limit int) []OAuthDebugLogEntry
	RecordOAuthDebug(level, stage, accountID, message string)
	RunAPISmokeTest(ctx context.Context, tenantID, ownerUID, accountID string) ([]APISmokeTestItem, error)
	RunAPIPlayground(ctx context.Context, tenantID, ownerUID, accountID string, req APIPlaygroundRequest) (*APIPlaygroundResult, error)
	ListPostPerformance(ctx context.Context, tenantID, ownerUID, accountID string, limit int) (*PostPerformanceResult, error)
	ResolveAccountAPIAccessToken(ctx context.Context, tenantID, ownerUID, accountID string) (string, error)
	RefreshAccountAPIAccessToken(ctx context.Context, tenantID, ownerUID, accountID string) (*SecretsData, error)
	ListTokenRefreshCandidates(ctx context.Context, leadTime time.Duration) ([]TokenRefreshCandidate, error)
	ResolveMemberCapabilities(ctx context.Context, tenantID, ownerUID string, research placement.ResearchSettings) (placement.MemberCapabilities, error)
	GetKnownAccounts(ctx context.Context, tenantID, ownerUID, accountID string) (map[string]entity.KnownAccountProfile, error)
	UpsertKnownAccountsFromScan(ctx context.Context, req UpsertKnownAccountsFromScanRequest) error
}
