package session

import (
	"log"
	"time"

	"metazone.cc/metalab/internal/config"
	"metazone.cc/metalab/internal/model"
)

// userStore SessionManager 对 UserRepo 的最小接口（ISP：1 个方法）
type userStore interface {
	FindByIDForAuth(userID uint) (*model.User, error)
}

// Manager 会话管理器：创建、验证、销毁、续期
type Manager struct {
	store    Store
	userRepo userStore
	cfg      *config.Config
}

// NewManager 构造函数
func NewManager(store Store, userRepo userStore, cfg *config.Config) *Manager {
	return &Manager{store: store, userRepo: userRepo, cfg: cfg}
}

// Create 创建会话并写入存储
func (m *Manager) Create(user *model.User, rememberMe bool, ip, userAgent string) (string, error) {
	sid, err := NewID()
	if err != nil {
		return "", err
	}
	now := time.Now()
	s := &Session{
		ID:         sid,
		UserID:     user.ID,
		Email:      user.Email,
		Username:   user.Username,
		Role:       user.Role,
		RememberMe: rememberMe,
		IP:         ip,
		UserAgent:  userAgent,
		CreatedAt:  now,
		LastAccess: now,
	}
	if err := m.store.Set(s); err != nil {
		return "", err
	}
	log.Printf("[SessionManager] Created sid=%s uid=%d rememberMe=%v ip=%s", sid[:16]+"...", user.ID, rememberMe, ip)
	return sid, nil
}

// Validate 验证会话：读取 → 检查过期 → 检查用户状态 → 续期 → 返回
// 返回 nil 表示会话无效（不存在/过期/用户被封禁）
func (m *Manager) Validate(sid string) (*Session, error) {
	if sid == "" {
		return nil, nil
	}

	s, err := m.store.Get(sid)
	if err != nil || s == nil {
		return nil, nil
	}

	// 检查用户是否仍然有效（封禁/注销后拒绝已有会话）
	user, err := m.userRepo.FindByIDForAuth(s.UserID)
	if err != nil {
		log.Printf("[SessionManager] Validate: user not found uid=%d err=%v", s.UserID, err)
		m.store.Delete(sid)
		return nil, nil
	}

	// 封禁用户直接拒绝
	if user.Status == model.StatusBanned {
		log.Printf("[SessionManager] Validate: user banned uid=%d", s.UserID)
		m.store.Delete(sid)
		return nil, nil
	}

	// 滑动窗口续期
	s.Touch()
	if err := m.store.Set(s); err != nil {
		log.Printf("[SessionManager] Validate: touch failed sid=%s err=%v", sid[:16]+"...", err)
	}

	return s, nil
}

// Destroy 销毁单个会话（用户主动退出登录）
func (m *Manager) Destroy(sid string) error {
	return m.store.Delete(sid)
}

// DestroyByUID 销毁某用户的所有会话（改密/注销/强制下线）
func (m *Manager) DestroyByUID(uid uint) error {
	return m.store.DeleteByUID(uid)
}

// IdleTimeout 根据 rememberMe 返回对应的空闲超时时间
func (m *Manager) IdleTimeout(rememberMe bool) time.Duration {
	if rememberMe {
		return time.Duration(m.cfg.Session.RememberTimeout) * time.Minute
	}
	return time.Duration(m.cfg.Session.IdleTimeout) * time.Minute
}

// ListByUID 列出某用户的所有活跃会话
func (m *Manager) ListByUID(uid uint) ([]*Session, error) {
	return m.store.ListByUID(uid)
}

// DestroyOtherByUID 销毁某用户除当前会话外的所有会话
func (m *Manager) DestroyOtherByUID(uid uint, currentSID string) error {
	return m.store.DeleteByUIDExclude(uid, currentSID)
}

// UpdateRemark 更新指定会话的备注（需验证归属）
func (m *Manager) UpdateRemark(sid string, uid uint, remark string) error {
	s, err := m.store.Get(sid)
	if err != nil || s == nil {
		return err
	}
	if s.UserID != uid {
		return nil
	}
	s.Remark = remark
	return m.store.Set(s)
}

// GetStoreMetrics 返回当前存储的状态信息
func (m *Manager) GetStoreMetrics() StoreMetrics {
	return m.store.Metrics()
}
