package service

import (
	"time"

	"metazone.cc/metalab/internal/model"

	"gorm.io/gorm"
)

// userAuthStore AuthService 所需的最小仓储接口（ISP：7 个方法）
type userAuthStore interface {
	ExistsByEmail(email string) (bool, error)
	Create(user *model.User) error
	FindByEmail(email string) (*model.User, error)
	FindByID(id uint) (*model.User, error)
	Update(user *model.User) error
	ExistsByUsername(username string) (bool, error)
}

// userAdminStore AdminService 所需的最小仓储接口（ISP：7 个方法）
type userAdminStore interface {
	CountSearchUsers(keyword, role, status string) (int64, error)
	SearchUsers(keyword, role, status string, offset, limit int) ([]model.User, error)
	FindByIDUnscoped(userID uint) (*model.User, error)
	UpdateStatus(uid uint, status string) error
	SoftDelete(uid uint) error
	Restore(uid uint) error
	ExistsByEmailExclude(email string, excludeUID uint) (bool, error)
}

// postStore PostService 所需的最小仓储接口
type postStore interface {
	Create(post *model.Post) error
	FindByID(id uint) (*model.Post, error)
	FindByIDWithAuthor(id uint) (*model.Post, error)
	FindPageable(keyword string, offset, limit int) ([]model.Post, int64, error)
	FindAdminPageable(keyword, status string, offset, limit int) ([]model.Post, int64, error)
	FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error)
	GetOverviewByUserID(userID uint) (totalPosts, draftCount, pendingCount, approvedCount, rejectedCount int64, err error)
	FindPendingRevisions(keyword string, offset, limit int) ([]model.Post, int64, error)
	Update(post *model.Post) error
	SoftDelete(id uint) error
	Restore(id uint) error
	RecordRead(userID, postID uint) (bool, error)
	RecordGuestRead(visitorID string, postID uint) (bool, error)
	IncrementViewsCount(postID uint) error
}

// spaceUserStore SpaceService 所需的最小用户仓储接口
type spaceUserStore interface {
	FindByID(id uint) (*model.User, error)
	Update(user *model.User) error
}

// spacePostStore SpaceService 所需的最小帖子仓储接口
type spacePostStore interface {
	FindByUserID(userID uint, offset, limit int) ([]model.Post, int64, error)
	CountUserPosts(userID uint) (int64, error)
	GetUserStats(userID uint) (likes, favorites, reads int64, err error)
}

// postAdminStatStore AdminService 所需的帖子统计接口（ISP：2 个方法）
type postAdminStatStore interface {
	CountPostsByStatus(status string) (int64, error)
	CountPending() (int64, error)
}

// userExpReader PostService 读取用户经验值的最小接口（ISP）
type userExpReader interface {
	FindByID(id uint) (*model.User, error)
}

// postNotifier PostService 所需的通知服务接口
type postNotifier interface {
	NotifyPostApproved(userID uint, postTitle string, postID uint)
	NotifyPostRejected(userID uint, postTitle, reason string, postID uint)
}

// userLevelStore LevelService 所需的用户仓储接口
type userLevelStore interface {
	FindByID(id uint) (*model.User, error)
	AddExp(userID uint, delta int) error
}

// checkInStore 签到记录仓储接口
type checkInStore interface {
	FindCheckIn(userID uint, date time.Time) (*model.UserCheckIn, error)
	CreateCheckIn(ci *model.UserCheckIn) error
}

// taskStore 任务完成记录仓储接口
type taskStore interface {
	FindTask(userID uint, taskType string) (*model.UserTask, error)
	CreateTask(task *model.UserTask) error
	HasTask(userID uint, taskType string) (bool, error)
}

// levelNotifier 等级升级通知接口
type levelNotifier interface {
	Create(userID uint, notifyType, title, content string, relatedID, commentID *uint) error
}

// EnergyStore EnergyService 所需的完整仓储接口
type EnergyStore interface {
	FindUserByID(userID uint) (*model.User, error)
	FindPostByID(postID uint) (*model.Post, error)
	AddEnergy(userID uint, amount int) error
	IncrPostEnergy(postID uint, amount int) error
	CreateEnergyLog(log *model.EnergyLog) error
	SumUserPostEnergy(userID, postID uint) (int, error)
	CreateEnergizeLog(log *model.PostEnergizeLog) error
	GetDailyEnergizeExp(userID uint, date time.Time) (*model.DailyExpSummary, error)
	UpsertDailyExp(summary *model.DailyExpSummary) error
	AddDailyExp(userID uint, date time.Time, delta int) error
	ListEnergyLogsByUser(userID uint, days int, offset, limit int) ([]model.EnergyLog, error)
	CountEnergyLogsByUser(userID uint, days int) (int64, error)
	ListAllEnergyLogs(energyType string, offset, limit int) ([]model.EnergyLog, int64, error)
	// WithTx 基于给定事务连接创建新的 EnergyStore（确保事务内操作原子性）
	WithTx(tx *gorm.DB) EnergyStore
	// Transaction 在事务内执行业务逻辑，自动管理 WithTx 和 FundStore 的事务范围
	Transaction(fn func(txEnergy EnergyStore, txFund FundStore) error) error
}

// energyStore 向后兼容别名
type energyStore = EnergyStore

// FundStore 公户仓储接口（ISP）
type FundStore interface {
	GetBalance() (int, error)
	LockAndGetBalance() (int, error)
	IncrBalance(amount int) error
	CreateLog(log *model.FundLog) error
	ListLogs(logType string, offset, limit int) ([]model.FundLog, int64, error)
	WithTx(tx *gorm.DB) FundStore
}

// energyNotifier EnergyService 所需的通知接口（ISP）
type energyNotifier interface {
	Create(userID uint, notifyType, title, content string, relatedID, commentID *uint) error
}

// commentStore CommentService 所需的最小仓储接口（ISP）
type commentStore interface {
	Create(comment *model.Comment) error
	UpdateRootID(id, rootID uint) error
	FindByID(id uint) (*model.Comment, error)
	FindRootComments(postID uint, offset, limit int) ([]model.Comment, int64, error)
	FindReplies(rootID uint) ([]model.Comment, error)
	SoftDelete(id uint) error
	IncrCommentsCount(postID uint) error
	DecrCommentsCount(postID uint) error
	CreateMention(mention *model.CommentMention) error
	FindPostIDByComment(commentID uint) (uint, error)
	FindPostAuthorID(postID uint) (uint, error)
	SearchUsersByLevel(keyword string, minLevel, limit int) ([]struct {
		UID      string
		Username string
		Exp      int
	}, error)
	GetUserUIDByID(userID uint) (string, error)
	GetUsernameByID(userID uint) (string, error)
	ListAllComments(keyword string, showDeleted bool, offset, limit int) ([]model.AdminCommentRow, int64, error)
}

// commentNotifier CommentService 所需的通知接口（ISP）
type commentNotifier interface {
	Create(userID uint, notifyType, title, content string, relatedID, commentID *uint) error
}

// ReactionStore ReactionService 所需的仓储接口（ISP）
type ReactionStore interface {
	FindLike(userID, postID uint) (*model.PostLike, error)
	CreateLike(like *model.PostLike) error
	DeleteLike(userID, postID uint) error
	FindDislike(userID, postID uint) (*model.PostDislike, error)
	CreateDislike(dislike *model.PostDislike) error
	DeleteDislike(userID, postID uint) error
	IncrPostLikes(postID uint, delta int) error
	IncrPostDislikes(postID uint, delta int) error
	GetPostAuthorID(postID uint) (uint, error)
	GetPostLikesCount(postID uint) (int, error)
	UpsertDailyLikeSummary(authorUID uint, date string, likerUID string) error
	GetUnnotifiedSummaries(userID uint) ([]model.DailyLikeSummary, error)
	MarkSummaryNotified(id uint) error
	WithTx(tx *gorm.DB) ReactionStore
	// Transaction 在事务内执行业务逻辑，自动管理 WithTx
	Transaction(fn func(tx ReactionStore) error) error
}

// FollowStore FollowService 所需的最小仓储接口（ISP）
type FollowStore interface {
	Create(follow *model.UserFollow) error
	Delete(followerID, followeeID uint) error
	Exists(followerID, followeeID uint) (bool, error)
	CountFollowers(userID uint) (int64, error)
	CountFollowing(userID uint) (int64, error)
	ListFollowers(userID uint, offset, limit int) ([]model.UserFollow, int64, error)
	ListFollowing(userID uint, offset, limit int) ([]model.UserFollow, int64, error)
	IncrFollowersCount(userID uint, delta int) error
	IncrFollowingCount(userID uint, delta int) error
	GetFollowListPublic(userID uint) (bool, error)
	WithTx(tx *gorm.DB) FollowStore
	// Transaction 在事务内执行业务逻辑，自动管理 WithTx
	Transaction(fn func(tx FollowStore) error) error
}

// TrendPoint 趋势数据点
type TrendPoint struct {
	Date  string `json:"date"`
	Value int    `json:"value"`
}

// EnergyTrendStore 赋能趋势聚合（ISP）
type EnergyTrendStore interface {
	AggregateEnergyByAuthor(userID uint, since string) ([]TrendPoint, error)
}

// CommentTrendStore 评论趋势聚合（ISP）
type CommentTrendStore interface {
	AggregateCommentsByAuthor(userID uint, since string) ([]TrendPoint, error)
}

// LikeTrendStore 点赞趋势聚合（ISP）
type LikeTrendStore interface {
	AggregateLikesByAuthor(userID uint, since string) ([]TrendPoint, error)
}

// FavoriteTrendStore 收藏趋势聚合（ISP）
type FavoriteTrendStore interface {
	AggregateFavoritesByAuthor(userID uint, since string) ([]TrendPoint, error)
}
