import crypto from "crypto";

interface SessionData {
  userId: number;
  openId: string;
  createdAt: number;
  lastActivityAt: number;
  rememberMe: boolean;
}

// In-memory session store (in production, use Redis or database)
const sessions = new Map<string, SessionData>();

const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
const REMEMBER_ME_TIMEOUT_MS = 7 * 24 * 60 * 60 * 1000; // 7 days

/**
 * Create a new session
 */
export function createSession(userId: number, openId: string, rememberMe: boolean = false): string {
  const sessionId = crypto.randomBytes(32).toString("hex");
  const now = Date.now();

  sessions.set(sessionId, {
    userId,
    openId,
    createdAt: now,
    lastActivityAt: now,
    rememberMe,
  });

  return sessionId;
}

/**
 * Get session data
 */
export function getSession(sessionId: string): SessionData | null {
  const session = sessions.get(sessionId);
  if (!session) return null;

  // Check if session has expired
  const timeout = session.rememberMe ? REMEMBER_ME_TIMEOUT_MS : SESSION_TIMEOUT_MS;
  const isExpired = Date.now() - session.lastActivityAt > timeout;

  if (isExpired) {
    sessions.delete(sessionId);
    return null;
  }

  return session;
}

/**
 * Update session activity
 */
export function updateSessionActivity(sessionId: string): boolean {
  const session = getSession(sessionId);
  if (!session) return false;

  session.lastActivityAt = Date.now();
  sessions.set(sessionId, session);
  return true;
}

/**
 * Destroy a session
 */
export function destroySession(sessionId: string): boolean {
  return sessions.delete(sessionId);
}

/**
 * Check if session is expired
 */
export function isSessionExpired(sessionId: string): boolean {
  const session = sessions.get(sessionId);
  if (!session) return true;

  const timeout = session.rememberMe ? REMEMBER_ME_TIMEOUT_MS : SESSION_TIMEOUT_MS;
  return Date.now() - session.lastActivityAt > timeout;
}

/**
 * Get session timeout in milliseconds
 */
export function getSessionTimeout(sessionId: string): number | null {
  const session = getSession(sessionId);
  if (!session) return null;

  const timeout = session.rememberMe ? REMEMBER_ME_TIMEOUT_MS : SESSION_TIMEOUT_MS;
  const timeRemaining = timeout - (Date.now() - session.lastActivityAt);
  return Math.max(0, timeRemaining);
}

/**
 * Refresh session (extend timeout)
 */
export function refreshSession(sessionId: string): boolean {
  return updateSessionActivity(sessionId);
}

/**
 * Clean up expired sessions (run periodically)
 */
export function cleanupExpiredSessions(): number {
  let cleaned = 0;

  for (const [sessionId, session] of sessions.entries()) {
    const timeout = session.rememberMe ? REMEMBER_ME_TIMEOUT_MS : SESSION_TIMEOUT_MS;
    if (Date.now() - session.lastActivityAt > timeout) {
      sessions.delete(sessionId);
      cleaned++;
    }
  }

  console.log(`[Session Management] Cleaned up ${cleaned} expired sessions`);
  return cleaned;
}

/**
 * Get session info (for debugging)
 */
export function getSessionInfo(sessionId: string) {
  const session = sessions.get(sessionId);
  if (!session) return null;

  const timeout = session.rememberMe ? REMEMBER_ME_TIMEOUT_MS : SESSION_TIMEOUT_MS;
  const timeRemaining = timeout - (Date.now() - session.lastActivityAt);

  return {
    userId: session.userId,
    openId: session.openId,
    rememberMe: session.rememberMe,
    createdAt: new Date(session.createdAt).toISOString(),
    lastActivityAt: new Date(session.lastActivityAt).toISOString(),
    timeRemaining: Math.max(0, timeRemaining),
    isExpired: timeRemaining <= 0,
  };
}

// Run cleanup every 5 minutes
setInterval(() => {
  cleanupExpiredSessions();
}, 5 * 60 * 1000);
