/**
 * 会话 Cookie 持久化：按 sessionKey 保存 cf_clearance 等，降低重复过盾概率
 */
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { RUNTIME_DIR, SESSION_TTL_MS } = require('./constants');

const SESSIONS_DIR = path.join(RUNTIME_DIR, 'sessions');

/**
 * 确保 sessions 目录存在
 */
function ensureSessionsDir() {
    fs.mkdirSync(SESSIONS_DIR, { recursive: true, mode: 0o777 });
}

/**
 * sessionKey 转安全文件名
 * @param {string} sessionKey
 * @returns {string}
 */
function keyToFilename(sessionKey) {
    const hash = crypto.createHash('md5').update(sessionKey).digest('hex');
    return `${hash}.json`;
}

/**
 * @typedef {Object} StoredSession
 * @property {string} sessionKey
 * @property {number} savedAt
 * @property {number} expiresAt
 * @property {Array<{name:string,value:string,domain?:string,path?:string}>} cookies
 */

/**
 * 加载已保存的会话 cookies
 * @param {string} sessionKey
 * @returns {StoredSession|null}
 */
function loadSession(sessionKey) {
    if (!sessionKey) return null;
    ensureSessionsDir();
    const filePath = path.join(SESSIONS_DIR, keyToFilename(sessionKey));
    if (!fs.existsSync(filePath)) return null;

    try {
        const raw = JSON.parse(fs.readFileSync(filePath, 'utf8'));
        if (!raw || !Array.isArray(raw.cookies)) return null;
        if (raw.expiresAt && Date.now() > raw.expiresAt) {
            fs.unlinkSync(filePath);
            return null;
        }
        return raw;
    } catch (_) {
        return null;
    }
}

/**
 * 保存会话 cookies（优先保留 CF 相关 cookie）
 * @param {string} sessionKey
 * @param {Array<{name:string,value:string,domain?:string,path?:string}>} cookies
 * @param {number} [ttlMs]
 */
function saveSession(sessionKey, cookies, ttlMs = SESSION_TTL_MS) {
    if (!sessionKey || !Array.isArray(cookies) || cookies.length === 0) return;
    ensureSessionsDir();

    const cfRelated = cookies.filter((c) =>
        ['cf_clearance', '__cf_bm', 'cf_chl_2'].includes(c.name)
        || c.name.startsWith('__cf')
    );

    const toSave = cfRelated.length > 0 ? cfRelated : cookies;
    const now = Date.now();
    const payload = {
        sessionKey,
        savedAt: now,
        expiresAt: now + ttlMs,
        cookies: toSave.map((c) => ({
            name: c.name,
            value: c.value,
            domain: c.domain,
            path: c.path || '/',
        })),
    };

    const filePath = path.join(SESSIONS_DIR, keyToFilename(sessionKey));
    fs.writeFileSync(filePath, JSON.stringify(payload, null, 0), { mode: 0o666 });
}

/**
 * 将会话 cookies 转为 puppeteer setCookie 格式
 * @param {StoredSession|null} session
 * @param {string} pageUrl
 * @returns {Array<{name:string,value:string,domain?:string,path?:string,url?:string}>}
 */
function sessionCookiesForPage(session, pageUrl) {
    if (!session || !Array.isArray(session.cookies)) return [];
    let hostname = '';
    try {
        hostname = new URL(pageUrl).hostname;
    } catch (_) {
        return session.cookies;
    }

    return session.cookies.map((c) => {
        const cookie = { ...c };
        if (!cookie.domain && hostname) {
            cookie.url = `https://${hostname}/`;
        }
        return cookie;
    });
}

module.exports = {
    loadSession,
    saveSession,
    sessionCookiesForPage,
};
