package com.flightticket.service;

import com.flightticket.dto.auth.TokenResponse;

import java.util.List;

/**
 * Service for managing user sessions with Redis storage
 * Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6
 */
public interface SessionManagementService {
    
    /**
     * Create a new session for a user
     * Requirement: 15.1
     * 
     * @param userId User ID
     * @param accessToken JWT access token
     * @param refreshToken JWT refresh token
     * @param expiresIn Token expiration time in seconds
     * @return Session ID
     */
    String createSession(String userId, String accessToken, String refreshToken, Long expiresIn);
    
    /**
     * Refresh an existing session with new tokens
     * Requirement: 15.2
     * 
     * @param sessionId Session ID
     * @param accessToken New JWT access token
     * @param refreshToken New JWT refresh token
     * @param expiresIn Token expiration time in seconds
     */
    void refreshSession(String sessionId, String accessToken, String refreshToken, Long expiresIn);
    
    /**
     * Check if a token needs to be refreshed (within refresh window)
     * Requirement: 15.2
     * 
     * @param sessionId Session ID
     * @return true if token should be refreshed
     */
    boolean shouldRefreshToken(String sessionId);
    
    /**
     * Invalidate a session on logout
     * Requirement: 15.3
     * 
     * @param sessionId Session ID
     */
    void invalidateSession(String sessionId);
    
    /**
     * Invalidate all sessions for a user
     * Requirement: 15.3
     * 
     * @param userId User ID
     */
    void invalidateAllUserSessions(String userId);
    
    /**
     * Check if a session is valid and not expired
     * Requirement: 15.4
     * 
     * @param sessionId Session ID
     * @return true if session is valid
     */
    boolean isSessionValid(String sessionId);
    
    /**
     * Get active session count for a user
     * Requirement: 15.5
     * 
     * @param userId User ID
     * @return Number of active sessions
     */
    int getActiveSessionCount(String userId);
    
    /**
     * Enforce concurrent session limit for a user
     * Terminates oldest session if limit is exceeded
     * Requirement: 15.5
     * 
     * @param userId User ID
     * @param maxSessions Maximum allowed concurrent sessions
     */
    void enforceConcurrentSessionLimit(String userId, int maxSessions);
    
    /**
     * Terminate a session due to suspicious activity
     * Requirement: 15.6
     * 
     * @param sessionId Session ID
     * @param reason Reason for termination
     */
    void terminateSessionForSuspiciousActivity(String sessionId, String reason);
    
    /**
     * Record a failed request for suspicious activity detection
     * Requirement: 15.6
     * 
     * @param sessionId Session ID
     */
    void recordFailedRequest(String sessionId);
    
    /**
     * Check if a session has suspicious activity
     * Requirement: 15.6
     * 
     * @param sessionId Session ID
     * @return true if suspicious activity detected
     */
    boolean hasSuspiciousActivity(String sessionId);
    
    /**
     * Get session information
     * 
     * @param sessionId Session ID
     * @return Session data or null if not found
     */
    SessionData getSession(String sessionId);
    
    /**
     * Get all active sessions for a user
     * 
     * @param userId User ID
     * @return List of session IDs
     */
    List<String> getUserSessions(String userId);
    
    /**
     * Update session last activity timestamp
     * 
     * @param sessionId Session ID
     */
    void updateLastActivity(String sessionId);
    
    /**
     * Session data holder
     */
    class SessionData {
        private String sessionId;
        private String userId;
        private String accessToken;
        private String refreshToken;
        private Long expiresAt;
        private Long createdAt;
        private Long lastActivityAt;
        private int failedRequestCount;
        private boolean terminated;
        private String terminationReason;
        
        public SessionData() {}
        
        public SessionData(String sessionId, String userId, String accessToken, 
                          String refreshToken, Long expiresAt, Long createdAt) {
            this.sessionId = sessionId;
            this.userId = userId;
            this.accessToken = accessToken;
            this.refreshToken = refreshToken;
            this.expiresAt = expiresAt;
            this.createdAt = createdAt;
            this.lastActivityAt = createdAt;
            this.failedRequestCount = 0;
            this.terminated = false;
        }
        
        // Getters and setters
        public String getSessionId() { return sessionId; }
        public void setSessionId(String sessionId) { this.sessionId = sessionId; }
        
        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }
        
        public String getAccessToken() { return accessToken; }
        public void setAccessToken(String accessToken) { this.accessToken = accessToken; }
        
        public String getRefreshToken() { return refreshToken; }
        public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; }
        
        public Long getExpiresAt() { return expiresAt; }
        public void setExpiresAt(Long expiresAt) { this.expiresAt = expiresAt; }
        
        public Long getCreatedAt() { return createdAt; }
        public void setCreatedAt(Long createdAt) { this.createdAt = createdAt; }
        
        public Long getLastActivityAt() { return lastActivityAt; }
        public void setLastActivityAt(Long lastActivityAt) { this.lastActivityAt = lastActivityAt; }
        
        public int getFailedRequestCount() { return failedRequestCount; }
        public void setFailedRequestCount(int failedRequestCount) { this.failedRequestCount = failedRequestCount; }
        
        public boolean isTerminated() { return terminated; }
        public void setTerminated(boolean terminated) { this.terminated = terminated; }
        
        public String getTerminationReason() { return terminationReason; }
        public void setTerminationReason(String terminationReason) { this.terminationReason = terminationReason; }
    }
}
