/**
 * session-loader.ts
 *
 * Shared helper for decrypting a browser session storageState blob.
 * Used by both:
 *   - src/engine/tools/user-folder.ts (RunUserScript tool)
 *   - src/bridge/user-folder-api.ts  (POST /scripts/:name/run endpoint)
 */

import type { BrowserSessionRepo } from '../db/browser-session-repo.js';
import { initMasterKey, decryptUserDek, decryptStateBlob } from '../crypto/sessions.js';
import { logger } from '../logger.js';

interface SessionLoaderDeps {
  sessRepo: BrowserSessionRepo;
  masterKeyPath: string;
}

export type SessionLoadError =
  | { kind: 'profile_not_found'; message: string }
  | { kind: 'profile_not_active'; message: string }
  | { kind: 'dek_not_found'; message: string }
  | { kind: 'decrypt_error'; message: string };

export type SessionLoadResult =
  | { ok: true; storageState: object }
  | { ok: false; error: SessionLoadError };

/**
 * Load and decrypt the storageState for the given session profile.
 *
 * Returns `{ ok: true, storageState }` on success.
 * Returns `{ ok: false, error }` when the profile is missing, wrong owner,
 * not active, or decryption fails.
 * Never throws — all errors are surfaced via the returned error shape.
 */
export async function loadSessionStateForUser(
  deps: SessionLoaderDeps,
  ownerId: string,
  sessionProfileId: number,
): Promise<SessionLoadResult> {
  const { sessRepo, masterKeyPath } = deps;

  // Owner-scoped lookup — ensures profile belongs to ownerId
  const profile = sessRepo.getProfileById(sessionProfileId, ownerId);
  if (!profile) {
    return {
      ok: false,
      error: {
        kind: 'profile_not_found',
        message: `session profile ${sessionProfileId} not found or does not belong to this user`,
      },
    };
  }

  if (profile.status !== 'active' || !profile.encryptedStateBlob) {
    return {
      ok: false,
      error: {
        kind: 'profile_not_active',
        message: `session profile ${sessionProfileId} is not active (status=${profile.status})`,
      },
    };
  }

  try {
    const master = initMasterKey(masterKeyPath);
    const encDek = sessRepo.getUserDek(ownerId);
    if (!encDek) {
      return {
        ok: false,
        error: {
          kind: 'dek_not_found',
          message: 'user DEK not found — the session profile has not been saved yet',
        },
      };
    }
    const dek = decryptUserDek(master, encDek);
    const stateJson = decryptStateBlob(dek, profile.encryptedStateBlob);
    const storageState = JSON.parse(stateJson) as object;
    return { ok: true, storageState };
  } catch (err) {
    logger.error(`[session-loader] storageState decrypt failed: ${(err as Error).message}`);
    return {
      ok: false,
      error: {
        kind: 'decrypt_error',
        message: `failed to decrypt session storageState: ${(err as Error).message}`,
      },
    };
  }
}
