// server/api/users/list.get.ts
// Get all users from database and enrich with last access from Keycloak

import Database from 'better-sqlite3';
import { join } from 'path';
import { existsSync, mkdirSync } from 'fs';

// Helper to get database path
const getDbPath = () => {
  const dbDir = join(process.cwd(), 'data');
  if (!existsSync(dbDir)) {
    mkdirSync(dbDir, { recursive: true });
  }
  return join(dbDir, 'users.db');
};

// Helper to decode JWT token payload
const decodeTokenPayload = (token: string | undefined): any | null => {
  if (!token) return null;
  try {
    const parts = token.split(".");
    if (parts.length < 2) return null;
    const payloadBase64 = parts[1];
    return JSON.parse(Buffer.from(payloadBase64, "base64").toString());
  } catch (e) {
    return null;
  }
};

// Helper to get last access from Keycloak for a user using access token from session
const getLastAccessFromKeycloak = async (userId: string, accessToken: string, config: any): Promise<number | null> => {
  try {
    if (!accessToken) {
      return null;
    }

    // Extract realm from issuer
    const issuerUrl = new URL(config.keycloakIssuer);
    const realm = issuerUrl.pathname.split('/').filter(Boolean).pop() || 'master';

    // Get user sessions from Keycloak Admin API using access token
    const sessionsUrl = `${config.keycloakIssuer.replace('/realms/' + realm, '')}/admin/realms/${realm}/users/${userId}/sessions`;
    
    const sessionsResponse = await fetch(sessionsUrl, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json',
      },
    });

    if (!sessionsResponse.ok) {
      if (sessionsResponse.status === 404 || sessionsResponse.status === 403) {
        // User has no sessions or no permission
        return null;
      }
      return null;
    }

    const sessions = await sessionsResponse.json() as any[];

    if (!sessions || sessions.length === 0) {
      return null;
    }

    // Find the most recent session (highest lastAccess timestamp)
    let lastAccessTimestamp = 0;
    sessions.forEach(session => {
      if (session.lastAccess && session.lastAccess > lastAccessTimestamp) {
        lastAccessTimestamp = session.lastAccess;
      }
    });

    // Convert from milliseconds to seconds (Unix timestamp)
    return lastAccessTimestamp > 0 ? Math.floor(lastAccessTimestamp / 1000) : null;
  } catch (error: any) {
    console.warn(`⚠️ Error fetching last access for user ${userId}:`, error.message);
    return null;
  }
};

// Helper to ensure database schema is up to date
const ensureSchema = (db: any) => {
  try {
    const tableInfo = db.prepare("PRAGMA table_info(users)").all() as any[];
    const columnNames = tableInfo.map(col => col.name);
    
    // Add missing columns one by one
    if (!columnNames.includes('realmRoles')) {
      db.exec(`ALTER TABLE users ADD COLUMN realmRoles TEXT DEFAULT '[]'`);
      console.log('✅ Added column: realmRoles');
    }
    
    if (!columnNames.includes('accountRoles')) {
      db.exec(`ALTER TABLE users ADD COLUMN accountRoles TEXT DEFAULT '[]'`);
      console.log('✅ Added column: accountRoles');
    }
    
    if (!columnNames.includes('resourceRoles')) {
      db.exec(`ALTER TABLE users ADD COLUMN resourceRoles TEXT DEFAULT '[]'`);
      console.log('✅ Added column: resourceRoles');
    }
    
    if (!columnNames.includes('lastLogin')) {
      db.exec(`ALTER TABLE users ADD COLUMN lastLogin INTEGER`);
      console.log('✅ Added column: lastLogin');
    }
    
    if (!columnNames.includes('given_name')) {
      db.exec(`ALTER TABLE users ADD COLUMN given_name TEXT`);
      console.log('✅ Added column: given_name');
    }
    
    if (!columnNames.includes('family_name')) {
      db.exec(`ALTER TABLE users ADD COLUMN family_name TEXT`);
      console.log('✅ Added column: family_name');
    }
  } catch (e: any) {
    console.error('❌ Schema migration error:', e.message);
  }
};

export default defineEventHandler(async (event) => {
  console.log("📋 Users list endpoint called");

  try {
    const config = useRuntimeConfig();
    const dbPath = getDbPath();
    
    // Check if database exists
    if (!existsSync(dbPath)) {
      console.log("ℹ️ Database not found, returning empty array");
      return [];
    }

    // Try to get access token from current user session
    let accessToken: string | null = null;
    try {
      const { getSessionFromCookie } = await import('~/server/utils/sessionStore');
      const session = await getSessionFromCookie(event);
      if (session && session.accessToken) {
        accessToken = session.accessToken;
      }
    } catch (e) {
      // No session available, will skip Keycloak fetch
      console.log("ℹ️ No valid session found, will use database values for last access");
    }

    // Open database connection
    const db = new Database(dbPath);
    
    // Ensure schema is up to date before querying
    ensureSchema(db);
    
    // Get all users
    const users = db.prepare('SELECT * FROM users ORDER BY updatedAt DESC').all() as any[];
    
    // Parse JSON fields and enrich with last access from Keycloak
    const formattedUsers = await Promise.all(users.map(async (user) => {
      // Get lastLogin from database (handle null, 0, or undefined)
      let lastLogin: number | null = null;
      if (user.lastLogin !== null && user.lastLogin !== undefined && user.lastLogin !== 0) {
        lastLogin = user.lastLogin;
      }
      
      // Only fetch from Keycloak if we have a valid user ID, access token, and config
      // And only if we don't have a valid lastLogin in database
      if (user.id && accessToken && config.keycloakIssuer) {
        try {
          const keycloakLastAccess = await getLastAccessFromKeycloak(user.id, accessToken, config);
          // Use Keycloak last access if available and newer than database value
          if (keycloakLastAccess) {
            if (!lastLogin || keycloakLastAccess > lastLogin) {
              lastLogin = keycloakLastAccess;
            }
          }
        } catch (error) {
          // Silently fail and use database value
          console.warn(`⚠️ Could not fetch last access for user ${user.id}, using database value`);
        }
      }

      return {
        id: user.id,
        namaLengkap: user.namaLengkap,
        namaUser: user.namaUser,
        email: user.email,
        tipeUser: user.tipeUser || '',
        lastLogin: lastLogin, // Will be null if never logged in, otherwise timestamp in seconds
        roles: JSON.parse(user.roles || '[]'),
        realmRoles: JSON.parse(user.realmRoles || '[]'),
        accountRoles: JSON.parse(user.accountRoles || '[]'),
        resourceRoles: JSON.parse(user.resourceRoles || '[]'),
        groups: JSON.parse(user.groups || '[]'),
        given_name: user.given_name,
        family_name: user.family_name,
        createdAt: user.createdAt,
        updatedAt: user.updatedAt,
      };
    }));
    
    db.close();
    
    console.log(`✅ Retrieved ${formattedUsers.length} users with last access data`);
    return formattedUsers;
  } catch (error: any) {
    console.error("❌ Error fetching users:", error);
    throw createError({
      statusCode: 500,
      statusMessage: error.message || "Failed to fetch users",
    });
  }
});

