import { request } from 'undici';
import { readFile } from 'node:fs/promises';
import { getTokenPath } from './home.js';
import { TEDebugClient } from '../te-debug/client.js';
import { t } from '../i18n/translate.js';
const DEFAULT_HOST = 'https://web-ta-demo.thinkingdata.cn';
function formatTeTime(d) {
    const pad = (n, w = 2) => String(n).padStart(w, '0');
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}`;
}
async function getToken(host) {
    let cache;
    try {
        cache = JSON.parse(await readFile(getTokenPath(), 'utf8'));
    }
    catch {
        throw new Error(t('auth.no_cached_token', { host }));
    }
    const tok = cache[host]?.token;
    if (!tok)
        throw new Error(t('auth.no_cached_token', { host }));
    return tok;
}
function parseProps(prop) {
    const out = {};
    for (const kv of prop) {
        const ix = kv.indexOf('=');
        if (ix > 0)
            out[kv.slice(0, ix)] = kv.slice(ix + 1);
    }
    return out;
}
function nowMinusOneHour() {
    const d = new Date(Date.now() - 60 * 60 * 1000);
    // YYYY-MM-DD HH:MM:SS in local time, matching what AE UI sends
    const pad = (n) => String(n).padStart(2, '0');
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
}
export function registerDebug(cmd) {
    cmd.description('AE Debug-mode utilities (devices, test events, watch)');
    // device subgroup
    const device = cmd.command('device').description('manage AE Debug devices');
    device.command('list')
        .requiredOption('--project <id>', 'AE projectId', (v) => parseInt(v, 10))
        .option('--host <url>', 'AE host', DEFAULT_HOST)
        .action(async (opts) => {
        const token = await getToken(opts.host);
        const list = await new TEDebugClient({ host: opts.host, token }).listDevice(opts.project);
        if (list.length === 0) {
            console.log(t('debug.no_devices'));
            return;
        }
        console.log(t('debug.device_header'));
        for (const d of list)
            console.log(`${d.deviceId}\t${d.deviceName}\t${d.lastClearTime ?? ''}`);
    });
    device.command('add')
        .requiredOption('--project <id>', 'AE projectId', (v) => parseInt(v, 10))
        .requiredOption('--device-id <id>', 'device identifier (becomes #device_id when sending events)')
        .requiredOption('--device-name <name>', 'human-readable label')
        .option('--host <url>', 'AE host', DEFAULT_HOST)
        .action(async (opts) => {
        const token = await getToken(opts.host);
        await new TEDebugClient({ host: opts.host, token }).addDevice(opts.project, opts.deviceId, opts.deviceName);
        console.log(t('debug.device_added', { deviceId: opts.deviceId }));
    });
    device.command('select')
        .requiredOption('--project <id>', 'AE projectId', (v) => parseInt(v, 10))
        .requiredOption('--device-id <id>')
        .option('--host <url>', 'AE host', DEFAULT_HOST)
        .action(async (opts) => {
        const token = await getToken(opts.host);
        await new TEDebugClient({ host: opts.host, token }).selectDevice(opts.project, opts.deviceId);
        console.log(t('debug.device_selected', { deviceId: opts.deviceId }));
    });
    device.command('remove')
        .requiredOption('--project <id>', 'AE projectId', (v) => parseInt(v, 10))
        .requiredOption('--device-id <id>')
        .option('--host <url>', 'AE host', DEFAULT_HOST)
        .action(async (opts) => {
        const token = await getToken(opts.host);
        await new TEDebugClient({ host: opts.host, token }).removeDevice(opts.project, opts.deviceId);
        console.log(t('debug.device_removed', { deviceId: opts.deviceId }));
    });
    // send: REST API connectivity + format validation (debug=1 for detailed errors)
    // NOTE: REST API events do NOT appear in AE Debug UI — that only shows
    // events from SDK instances initialized with mode:'debug'. This command
    // validates receiver reachability, appId correctness, and data format.
    cmd.command('send')
        .description('validate connectivity: POST a test event via REST API (does NOT appear in Debug UI)')
        .requiredOption('--receiver <url>', 'AE data receiver URL')
        .requiredOption('--appid <id>', 'AE appId')
        .requiredOption('--event <name>', 'event name')
        .option('--distinct-id <id>', '#distinct_id', 'claude-test')
        .option('--prop <kv...>', 'k=v pairs (repeatable)', [])
        .action(async (opts) => {
        const body = {
            appid: opts.appid,
            debug: 1,
            data: {
                '#type': 'track',
                '#event_name': opts.event,
                '#time': formatTeTime(new Date()),
                '#distinct_id': opts.distinctId,
                properties: parseProps(opts.prop),
            },
        };
        const url = opts.receiver.replace(/\/$/, '') + '/sync_json';
        const { statusCode, body: resBody } = await request(url, {
            method: 'POST',
            headers: { 'content-type': 'application/json' },
            body: JSON.stringify(body),
        });
        const text = await resBody.text();
        console.log(`HTTP ${statusCode}`);
        console.log(text);
        if (statusCode === 200) {
            try {
                const r = JSON.parse(text);
                if (r.code === 0)
                    console.log('\n' + t('debug.validation_passed'));
                else
                    console.log('\n' + t('debug.validation_failed', { message: r.msg ?? 'unknown error' }));
            }
            catch { }
        }
    });
    // watch: one-shot snapshot of SDK debug events (requires SDK initialized with mode:'debug')
    cmd.command('watch')
        .description('pull events from a device running SDK in debug mode (one-shot snapshot)')
        .requiredOption('--project <id>', 'AE projectId', (v) => parseInt(v, 10))
        .requiredOption('--device-id <id>')
        .option('--host <url>', 'AE host', DEFAULT_HOST)
        .option('--since <iso>', 'startTime in YYYY-MM-DD HH:MM:SS local time (default: 1 hour ago)')
        .action(async (opts) => {
        const token = await getToken(opts.host);
        const since = opts.since ?? nowMinusOneHour();
        const data = await new TEDebugClient({ host: opts.host, token }).listDeviceData(opts.project, opts.deviceId, since);
        const total = data.eventList.length + data.deviceDataList.length;
        if (total === 0) {
            console.log(t('debug.no_events_received', { since }));
            return;
        }
        console.log(t('debug.event_list_header', { count: data.eventList.length }));
        for (const e of data.eventList)
            console.log('  ' + JSON.stringify(e));
        console.log(t('debug.device_data_header', { count: data.deviceDataList.length }));
        for (const e of data.deviceDataList)
            console.log('  ' + JSON.stringify(e));
        console.log('\n' + t('debug.raw_header'));
        console.log(JSON.stringify(data, null, 2));
    });
}
