-- ============================================================================
-- OrbiQuant IA - Trading Platform
-- Schema: auth
-- File: tables/04-sessions.sql
-- Description: User session management for authentication
-- ============================================================================

CREATE TABLE auth.sessions (
  -- Primary Key
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

  -- Foreign Key to Users
  user_id UUID NOT NULL,

  -- Session Token
  session_token VARCHAR(255) NOT NULL UNIQUE,

  -- Token Rotation (for security)
  refresh_token_hash VARCHAR(64),
  refresh_token_issued_at TIMESTAMPTZ,

  -- Session Lifecycle
  expires_at TIMESTAMPTZ NOT NULL,
  is_active BOOLEAN NOT NULL DEFAULT true,

  -- Session Metadata
  ip_address INET,
  user_agent TEXT,
  device_type VARCHAR(50),
  device_name VARCHAR(100),
  browser VARCHAR(50),
  os VARCHAR(50),

  -- Geolocation
  country_code VARCHAR(2),
  city VARCHAR(100),

  -- Security
  last_activity_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  invalidated_at TIMESTAMPTZ,
  invalidation_reason VARCHAR(100),

  -- Audit Fields
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  -- Foreign Key Constraints
  CONSTRAINT fk_sessions_user FOREIGN KEY (user_id)
    REFERENCES auth.users(id)
    ON DELETE CASCADE,

  -- Check Constraints
  CONSTRAINT valid_session_dates CHECK (expires_at > created_at),
  CONSTRAINT invalidated_consistency CHECK (
    (is_active = false AND invalidated_at IS NOT NULL) OR
    (is_active = true AND invalidated_at IS NULL)
  )
);

-- Indexes for Performance
CREATE INDEX idx_sessions_user_id ON auth.sessions(user_id);
CREATE INDEX idx_sessions_token ON auth.sessions(session_token);
CREATE INDEX idx_sessions_expires_at ON auth.sessions(expires_at);
CREATE INDEX idx_sessions_active ON auth.sessions(is_active, expires_at) WHERE is_active = true;
CREATE INDEX idx_sessions_last_activity ON auth.sessions(last_activity_at DESC);
CREATE INDEX idx_sessions_ip_address ON auth.sessions(ip_address);
CREATE INDEX idx_sessions_user_active ON auth.sessions(user_id, is_active, expires_at)
  WHERE is_active = true;

-- Table Comments
COMMENT ON TABLE auth.sessions IS 'User session management for authentication and activity tracking';

-- Column Comments
COMMENT ON COLUMN auth.sessions.id IS 'Unique identifier for the session';
COMMENT ON COLUMN auth.sessions.user_id IS 'Reference to the user account';
COMMENT ON COLUMN auth.sessions.session_token IS 'Unique session token for authentication';
COMMENT ON COLUMN auth.sessions.refresh_token_hash IS 'SHA-256 hash of refresh token for rotation security';
COMMENT ON COLUMN auth.sessions.refresh_token_issued_at IS 'Timestamp when current refresh token was issued';
COMMENT ON COLUMN auth.sessions.expires_at IS 'Session expiration timestamp';
COMMENT ON COLUMN auth.sessions.is_active IS 'Whether the session is currently active';
COMMENT ON COLUMN auth.sessions.ip_address IS 'IP address of the session';
COMMENT ON COLUMN auth.sessions.user_agent IS 'User agent string from the browser';
COMMENT ON COLUMN auth.sessions.device_type IS 'Device type (desktop, mobile, tablet)';
COMMENT ON COLUMN auth.sessions.device_name IS 'Device name or model';
COMMENT ON COLUMN auth.sessions.browser IS 'Browser name and version';
COMMENT ON COLUMN auth.sessions.os IS 'Operating system name and version';
COMMENT ON COLUMN auth.sessions.country_code IS 'Country code from IP geolocation';
COMMENT ON COLUMN auth.sessions.city IS 'City from IP geolocation';
COMMENT ON COLUMN auth.sessions.last_activity_at IS 'Timestamp of last session activity';
COMMENT ON COLUMN auth.sessions.invalidated_at IS 'Timestamp when session was invalidated';
COMMENT ON COLUMN auth.sessions.invalidation_reason IS 'Reason for session invalidation';
COMMENT ON COLUMN auth.sessions.created_at IS 'Timestamp when session was created';
COMMENT ON COLUMN auth.sessions.updated_at IS 'Timestamp when session was last updated';
