'use strict';
/**
 * sessionDiag.js — Diagnóstico de sesiones guardadas de CloakBrowser.
 *
 * Lee las cookies del perfil de CloakBrowser en sessions/<username>/ y muestra
 * cuáles están presentes, sus valores (truncados) y si la sesión parece válida.
 *
 * Usa el mismo mecanismo que chromeImporter: DPAPI para descifrar la master key
 * del Local State, luego AES-256-GCM para leer las cookies del SQLite.
 *
 * IMPORTANTE: Solo funciona en Windows (DPAPI). En Linux/Mac las cookies de
 * Playwright no están encriptadas (o usan libsecret), ajustar si es necesario.
 */

const fs   = require('fs');
const path = require('path');
const os   = require('os');

// Reutilizar el lector SQLite y DPAPI del chromeImporter
const {
    dpApiDecrypt,
    decryptChromeValue,
    parseChromeDb,
} = (() => {
    // Inline las funciones que necesitamos del chromeImporter
    // (requieren los mismos módulos: fs, path, crypto, spawnSync)
    return require('./chromeImporter');
})();

/**
 * Lee el Local State de un perfil de CloakBrowser/Chromium y descifra
 * la master key AES-256 con DPAPI. Luego lee las cookies del SQLite.
 *
 * @param {string} profileDir — ruta a la carpeta de sesión (ej. sessions/zoe_dgld)
 * @returns {object} diagnóstico con lista de cookies y estado de la sesión
 */
async function dpApiDecryptFromLocalState(profileDir) {
    // ── 1. Encontrar Local State ──────────────────────────────────────────────
    const localStatePath = path.join(profileDir, 'Local State');
    if (!fs.existsSync(localStatePath)) {
        // Si no hay Local State, el perfil es nuevo o nunca se usó
        return {
            hasLocalState: false,
            hasCookies: false,
            cookies: [],
            verdict: 'PERFIL_VACÍO',
            verdictMsg: 'No hay Local State — perfil nunca inicializado o vacío',
        };
    }

    // ── 2. Descifrar master key ───────────────────────────────────────────────
    let masterKey;
    try {
        const localState = JSON.parse(fs.readFileSync(localStatePath, 'utf8'));
        const encKeyB64  = localState?.os_crypt?.encrypted_key;
        if (!encKeyB64) {
            // Playwright en Linux no usa DPAPI — las cookies no están encriptadas
            masterKey = null;
        } else {
            const encKey = Buffer.from(encKeyB64, 'base64').slice(5); // quitar "DPAPI"
            masterKey = dpApiDecrypt(encKey);
        }
    } catch (e) {
        return {
            hasLocalState: true,
            hasCookies: false,
            cookies: [],
            verdict: 'ERROR_MASTER_KEY',
            verdictMsg: `No se pudo descifrar la master key: ${e.message}`,
        };
    }

    // ── 3. Encontrar archivo Cookies ──────────────────────────────────────────
    const cookiesFile = [
        path.join(profileDir, 'Network', 'Cookies'),
        path.join(profileDir, 'Cookies'),
        path.join(profileDir, 'Default', 'Network', 'Cookies'),
        path.join(profileDir, 'Default', 'Cookies'),
    ].find(p => fs.existsSync(p));

    if (!cookiesFile) {
        return {
            hasLocalState: true,
            hasCookies: false,
            cookies: [],
            verdict: 'SIN_COOKIES',
            verdictMsg: 'Hay Local State pero no hay archivo de cookies — sesión incompleta',
        };
    }

    // ── 4. Leer y descifrar cookies ───────────────────────────────────────────
    const tmp = path.join(os.tmpdir(), `xponencia_diag_${Date.now()}.sqlite`);
    fs.copyFileSync(cookiesFile, tmp);

    let parsed;
    try {
        parsed = parseChromeDb(tmp, 'instagram.com');
    } finally {
        try { fs.unlinkSync(tmp); } catch (_) {}
    }

    const { rows, cols } = parsed;

    // Mapeo de columnas (mismo que chromeImporter)
    const COL = { host_key: 1, name: 2, value: 3, encrypted_value: 4, path: 5 };
    if (cols) {
        for (const k of Object.keys(COL)) {
            const i = cols.indexOf(k);
            if (i !== -1) COL[k] = i;
        }
    }

    const cookies = [];
    for (const row of rows) {
        const name     = row[COL.name]  ?? '';
        const encVal   = row[COL.encrypted_value] ?? Buffer.alloc(0);
        const rawVal   = row[COL.value] ?? '';
        const hostKey  = row[COL.host_key] ?? '';

        if (!name || !String(hostKey).includes('instagram.com')) continue;

        let value = '';
        if (masterKey && Buffer.isBuffer(encVal) && encVal.length > 0) {
            value = decryptChromeValue(encVal, masterKey);
        } else if (typeof rawVal === 'string' && rawVal) {
            value = rawVal;
        }

        cookies.push({
            name,
            // Truncar para no exponer tokens completos en logs
            valuePreview: value ? value.slice(0, 12) + (value.length > 12 ? '…' : '') : '(vacío)',
            hasValue: value.length > 0,
        });
    }

    // ── 5. Análisis del estado ────────────────────────────────────────────────
    const cookieNames = new Set(cookies.map(c => c.name));

    const hasIgDid     = cookieNames.has('ig_did');
    const hasSessionId = cookieNames.has('sessionid');
    const hasMid       = cookieNames.has('mid');
    const hasDsUserId  = cookieNames.has('ds_user_id');

    // Fecha de creación del directorio (aproximación de cuándo fue el login)
    let createdAt = null;
    try {
        createdAt = fs.statSync(profileDir).birthtime?.toLocaleDateString('es-AR') ?? null;
    } catch (_) {}

    let verdict, verdictMsg;
    if (hasSessionId && hasIgDid) {
        verdict = 'SESIÓN_ACTIVA';
        verdictMsg = '✅ Sesión completa: ig_did + sessionid presentes';
    } else if (hasSessionId && !hasIgDid) {
        verdict = 'SESIÓN_SIN_IGDID';
        verdictMsg = '⚠️ Tiene sessionid pero NO tiene ig_did — posiblemente generado antes del fix de Chrome import. Recomendado: reiniciar sesión.';
    } else if (!hasSessionId && hasIgDid) {
        verdict = 'SOLO_IGDID';
        verdictMsg = '⚠️ Tiene ig_did pero no sessionid — nunca se completó el login';
    } else {
        verdict = 'SESIÓN_VACÍA';
        verdictMsg = '❌ Sin ig_did ni sessionid — perfil creado pero login incompleto o fallido';
    }

    return {
        hasLocalState: true,
        hasCookies: true,
        cookieCount: cookies.length,
        cookies,
        hasIgDid,
        hasSessionId,
        hasMid,
        hasDsUserId,
        createdAt,
        verdict,
        verdictMsg,
    };
}

module.exports = { dpApiDecryptFromLocalState };
