// server/api/users/[id].patch.ts
// Update user data

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

const getDbPath = () => {
  const dbDir = join(process.cwd(), 'data');
  return join(dbDir, 'users.db');
};

export default defineEventHandler(async (event) => {
  const userId = getRouterParam(event, 'id');
  const body = await readBody(event);

  console.log(`🔄 Update user endpoint called for ID: ${userId}`);

  if (!userId) {
    throw createError({
      statusCode: 400,
      statusMessage: "User ID is required",
    });
  }

  try {
    const dbPath = getDbPath();
    
    if (!existsSync(dbPath)) {
      throw createError({
        statusCode: 404,
        statusMessage: "Database not found",
      });
    }

    const db = new Database(dbPath);
    
    // Ensure schema is up to date
    try {
      const tableInfo = db.prepare("PRAGMA table_info(users)").all() as any[];
      const columnNames = tableInfo.map(col => col.name);
      
      if (!columnNames.includes('lastLogin')) {
        db.exec(`ALTER TABLE users ADD COLUMN lastLogin INTEGER`);
        console.log('✅ Added column: lastLogin');
      }
      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');
      }
    } catch (e: any) {
      console.warn('Migration note:', e.message);
    }
    
    // Check if user exists
    const existingUser = db.prepare('SELECT * FROM users WHERE id = ?').get(userId) as any;
    
    if (!existingUser) {
      db.close();
      throw createError({
        statusCode: 404,
        statusMessage: "User not found",
      });
    }

    // Handle password update to Keycloak if password is provided
    if (body.password && body.password.trim() !== '') {
      try {
        const config = useRuntimeConfig();
        
        // 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) {
          console.warn("⚠️ No valid session found for password update");
        }

        if (!accessToken) {
          db.close();
          throw createError({
            statusCode: 401,
            statusMessage: "Authentication required to update password",
          });
        }

        // Extract realm from issuer
        const issuerUrl = new URL(config.keycloakIssuer);
        const realm = issuerUrl.pathname.split('/').filter(Boolean).pop() || 'master';
        const keycloakBaseUrl = config.keycloakIssuer.replace('/realms/' + realm, '');
        const passwordUpdateUrl = `${keycloakBaseUrl}/admin/realms/${realm}/users/${userId}/reset-password`;

        console.log(`🔐 Updating password for user ${userId} in Keycloak`);
        console.log(`🔗 Password update URL: ${passwordUpdateUrl}`);

        // Create abort controller for timeout
        const controller = new AbortController();
        const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout

        // Update password in Keycloak
        let passwordResponse;
        try {
          passwordResponse = await fetch(passwordUpdateUrl, {
            method: 'PUT',
            headers: {
              'Authorization': `Bearer ${accessToken}`,
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({
              type: 'password',
              value: body.password,
              temporary: false, // Set to true if you want to force password change on next login
            }),
            signal: controller.signal,
          });
          clearTimeout(timeoutId);
        } catch (fetchError: any) {
          clearTimeout(timeoutId);
          console.error('❌ Fetch error during password update:');
          console.error('   - Error type:', fetchError.name);
          console.error('   - Error message:', fetchError.message);
          console.error('   - URL attempted:', passwordUpdateUrl);
          
          db.close();
          let errorMsg = 'Failed to connect to Keycloak server to update password.';
          if (fetchError.name === 'AbortError' || fetchError.message.includes('timeout')) {
            errorMsg = 'Keycloak server timeout. Please try again.';
          } else if (fetchError.message.includes('ENOTFOUND') || fetchError.message.includes('getaddrinfo')) {
            errorMsg = 'Cannot reach Keycloak server. Please check network connection.';
          } else if (fetchError.message.includes('ECONNREFUSED')) {
            errorMsg = 'Keycloak server refused connection. Server may be down.';
          } else if (fetchError.message.includes('certificate') || fetchError.message.includes('SSL')) {
            errorMsg = 'SSL certificate error. Please contact administrator.';
          }
          
          throw createError({
            statusCode: 500,
            statusMessage: errorMsg,
          });
        }

        if (!passwordResponse.ok) {
          const errorText = await passwordResponse.text();
          console.error('❌ Keycloak password update failed:', errorText);
          db.close();
          throw createError({
            statusCode: passwordResponse.status,
            statusMessage: `Failed to update password in Keycloak: ${errorText}`,
          });
        }

        console.log(`✅ Password updated successfully in Keycloak for user ${userId}`);
      } catch (passwordError: any) {
        console.error('❌ Error updating password in Keycloak:', passwordError);
        db.close();
        // Re-throw if it's already a createError
        if (passwordError.statusCode) {
          throw passwordError;
        }
        throw createError({
          statusCode: 500,
          statusMessage: `Failed to update password: ${passwordError.message}`,
        });
      }
    }

    // Prepare update fields
    const updateFields: string[] = [];
    const updateValues: any[] = [];

    if (body.namaLengkap !== undefined) {
      updateFields.push('namaLengkap = ?');
      updateValues.push(body.namaLengkap);
    }
    if (body.tipeUser !== undefined) {
      updateFields.push('tipeUser = ?');
      updateValues.push(body.tipeUser);
    }
    if (body.lastLogin !== undefined) {
      updateFields.push('lastLogin = ?');
      updateValues.push(body.lastLogin);
    }
    if (body.roles !== undefined) {
      updateFields.push('roles = ?');
      updateValues.push(JSON.stringify(Array.isArray(body.roles) ? body.roles : []));
    }
    if (body.realmRoles !== undefined) {
      updateFields.push('realmRoles = ?');
      updateValues.push(JSON.stringify(Array.isArray(body.realmRoles) ? body.realmRoles : []));
    }
    if (body.accountRoles !== undefined) {
      updateFields.push('accountRoles = ?');
      updateValues.push(JSON.stringify(Array.isArray(body.accountRoles) ? body.accountRoles : []));
    }
    if (body.resourceRoles !== undefined) {
      updateFields.push('resourceRoles = ?');
      updateValues.push(JSON.stringify(Array.isArray(body.resourceRoles) ? body.resourceRoles : []));
    }
    if (body.groups !== undefined) {
      updateFields.push('groups = ?');
      updateValues.push(JSON.stringify(Array.isArray(body.groups) ? body.groups : []));
    }

    if (updateFields.length === 0) {
      db.close();
      return { success: true, message: 'No fields to update' };
    }

    // Add updatedAt
    updateFields.push('updatedAt = strftime(\'%s\', \'now\')');
    updateValues.push(userId);

    // Execute update
    const sql = `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`;
    db.prepare(sql).run(...updateValues);
    
    db.close();
    
    console.log(`✅ User updated: ${userId}`);
    return { success: true, message: 'User updated successfully' };
  } catch (error: any) {
    console.error("❌ Error updating user:", error);
    throw createError({
      statusCode: error.statusCode || 500,
      statusMessage: error.message || "Failed to update user",
    });
  }
});

