package service

import (
	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/model"
	"metazone.cc/metalab/internal/session"
)

type AdminService struct {
	userRepo       userAdminStore
	postRepo       postAdminStatStore
	sessionManager *session.Manager
}

// PostStats 帖子统计结果（管理首页用）
type PostStats struct {
	Total    int64 // 全部未删除帖子数
	Approved int64 // 已发布数
	Pending  int64 // 待审核数（pending + 待审修订）
}

// NewAdminService 构造函数
func NewAdminService(userRepo userAdminStore, postRepo postAdminStatStore, sm *session.Manager) *AdminService {
	return &AdminService{userRepo: userRepo, postRepo: postRepo, sessionManager: sm}
}

// ListUsersParams 用户列表查询参数
type ListUsersParams struct {
	Keyword  string // 搜索关键字（邮箱/用户名）
	Role     string // 角色筛选
	Status   string // 状态筛选
	Page     int    // 页码
	PageSize int    // 每页条数
}

// ListUsersResult 用户列表查询结果
type ListUsersResult struct {
	Users []model.User `json:"users"`
	Total int64        `json:"total"`
	Page  int          `json:"page"`
}

// ListUsers 分页搜索用户列表
func (s *AdminService) ListUsers(params ListUsersParams) (*ListUsersResult, error) {
	p := common.Pagination{Page: params.Page, PageSize: params.PageSize}
	p.DefaultPagination()

	total, err := s.userRepo.CountSearchUsers(params.Keyword, params.Role, params.Status)
	if err != nil {
		return nil, err
	}

	users, err := s.userRepo.SearchUsers(params.Keyword, params.Role, params.Status, p.Offset(), p.PageSize)
	if err != nil {
		return nil, err
	}

	return &ListUsersResult{
		Users: users,
		Total: total,
		Page:  p.Page,
	}, nil
}

// UpdateUserStatus 修改用户状态
// 权限规则：
//   - 不可操作自己
//   - Admin 只能设置 active/banned，且只能操作 RoleUser
//   - Owner 可设置 active/banned/locked，可操作任何人（除自己）
func (s *AdminService) UpdateUserStatus(operatorUID, targetUID uint, newStatus string) error {
	// 校验状态值合法性
	switch newStatus {
	case model.StatusActive, model.StatusBanned, model.StatusLocked:
	default:
		return common.ErrPermissionDenied
	}

	return s.checkAndOperate(operatorUID, targetUID, func(operator, target *model.User) error {
		// locked 相关操作仅 owner
		if target.Status == model.StatusLocked || newStatus == model.StatusLocked {
			if !model.HasMinRole(operator.Role, model.RoleOwner) {
				return common.ErrPermissionDenied
			}
		}
		if err := s.userRepo.UpdateStatus(target.ID, newStatus); err != nil {
			return err
		}
		// 锁定（删除）→ GORM 软删除释放邮箱；解锁 → 先查邮箱冲突再恢复
		if newStatus == model.StatusLocked {
			if err := s.userRepo.SoftDelete(target.ID); err != nil {
				return err
			}
		} else if target.Status == model.StatusLocked && newStatus == model.StatusActive {
			// 检查邮箱是否已被新用户注册（软删期间邮箱释放了）
			collision, err := s.userRepo.ExistsByEmailExclude(target.Email, target.ID)
			if err != nil {
				return err
			}
			if collision {
				return common.ErrEmailExists
			}
			if err := s.userRepo.Restore(target.ID); err != nil {
				return err
			}
		}
		// 修改状态必须立刻让已有 session 失效
		return s.sessionManager.DestroyByUID(target.ID)
	})
}

// ResetUserToken 强制下线：销毁所有 session
func (s *AdminService) ResetUserToken(operatorUID, targetUID uint) error {
	return s.checkAndOperate(operatorUID, targetUID, func(_ *model.User, target *model.User) error {
		return s.sessionManager.DestroyByUID(target.ID)
	})
}

// CountUsers 统计用户总数（管理首页用）
func (s *AdminService) CountUsers() (int64, error) {
	return s.userRepo.CountSearchUsers("", "", "")
}

// GetPostStats 获取帖子统计（管理首页用）
func (s *AdminService) GetPostStats() (*PostStats, error) {
	total, err := s.postRepo.CountPostsByStatus("")
	if err != nil {
		return nil, err
	}
	approved, err := s.postRepo.CountPostsByStatus(model.PostStatusApproved)
	if err != nil {
		return nil, err
	}
	pending, err := s.postRepo.CountPending()
	if err != nil {
		return nil, err
	}
	return &PostStats{Total: total, Approved: approved, Pending: pending}, nil
}

// GetStoreMetrics 返回会话存储状态信息（管理首页用）
func (s *AdminService) GetStoreMetrics() session.StoreMetrics {
	return s.sessionManager.GetStoreMetrics()
}

// checkAndOperate 通用权限检查 + 执行操作
func (s *AdminService) checkAndOperate(operatorUID, targetUID uint, operate func(*model.User, *model.User) error) error {
	// 1. 不可操作自己
	if operatorUID == targetUID {
		return common.ErrPermissionDenied
	}

	// 2. 查操作者
	operator, err := s.userRepo.FindByIDUnscoped(operatorUID)
	if err != nil {
		return common.ErrUserNotFound
	}

	// 3. 查目标（含软删除用户，locked 解锁需要查到）
	target, err := s.userRepo.FindByIDUnscoped(targetUID)
	if err != nil {
		return common.ErrUserNotFound
	}

	// 4. 权限检查：操作者是否有权限操作目标角色
	if !model.CanOperateRole(operator.Role, target.Role) {
		return common.ErrPermissionDenied
	}

	return operate(operator, target)
}
