"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildCaptureRemoteCommandArgs = buildCaptureRemoteCommandArgs;
exports.captureRemote = captureRemote;
const node_path_1 = require("node:path");
const types_1 = require("@playdrop/types");
const commandContext_1 = require("../commandContext");
const http_1 = require("../http");
const messages_1 = require("../messages");
const devShared_1 = require("./devShared");
const captureRuntime_1 = require("../captureRuntime");
function readUnsupportedPlaydropCaptureMessage(targetUrl) {
    let parsed;
    try {
        parsed = new URL(targetUrl);
    }
    catch {
        return null;
    }
    const hostname = parsed.hostname.toLowerCase();
    const isPlaydropHost = hostname === 'www.playdrop.ai'
        || hostname === 'playdrop.ai'
        || hostname === 'localhost'
        || hostname === '127.0.0.1';
    if (!isPlaydropHost) {
        return null;
    }
    const pathname = parsed.pathname.replace(/\/+$/, '') || '/';
    const matchesCreatorAppRoute = /^\/(?:_auth\/)?creators\/[^/]+\/apps\/[^/]+\/[^/]+(?:\/.*)?$/i.test(pathname);
    if (!matchesCreatorAppRoute || pathname.endsWith('/play')) {
        return null;
    }
    return `Only Playdrop /play URLs are supported for remote capture. Use ${parsed.origin}${pathname}/play instead.`;
}
function parseTimeout(raw) {
    if (raw === undefined) {
        return 10;
    }
    const parsed = typeof raw === 'number' ? raw : Number.parseFloat(String(raw));
    if (!Number.isFinite(parsed) || parsed <= 0 || parsed > 600) {
        throw new Error('invalid_timeout');
    }
    return parsed;
}
function assertValidUrl(value, errorCode) {
    try {
        new URL(value);
    }
    catch {
        throw new Error(errorCode);
    }
}
function parseCredentialPair(options) {
    const username = options.username?.trim() || '';
    const password = options.password || '';
    if ((username && !password) || (!username && password)) {
        throw new Error('invalid_credentials_pair');
    }
    return { username, password };
}
function pushOptionalArg(args, flag, value) {
    if (!value?.trim()) {
        return;
    }
    args.push(flag, value.trim());
}
function buildCaptureRemoteCommandArgs(url, options = {}) {
    const trimmedUrl = typeof url === 'string' ? url.trim() : '';
    if (!trimmedUrl) {
        return null;
    }
    const { username, password } = parseCredentialPair(options);
    const args = ['--url', trimmedUrl];
    if (options.timeout !== undefined) {
        args.push('--timeout', String(parseTimeout(options.timeout)));
    }
    pushOptionalArg(args, '--screenshot', options.screenshot);
    pushOptionalArg(args, '--log', options.log);
    pushOptionalArg(args, '--expected-url', options.expectedUrl);
    if (username) {
        args.push('--username', username, '--password', password);
    }
    pushOptionalArg(args, '--login-url', options.loginUrl);
    return args;
}
function parseOptions(url, options = {}) {
    const trimmedUrl = typeof url === 'string' ? url.trim() : '';
    if (!trimmedUrl) {
        throw new Error('missing_url');
    }
    assertValidUrl(trimmedUrl, 'invalid_url');
    const expectedUrl = options.expectedUrl?.trim() || null;
    if (expectedUrl) {
        assertValidUrl(expectedUrl, 'invalid_expected_url');
    }
    const unsupportedPlaydropCaptureMessage = readUnsupportedPlaydropCaptureMessage(trimmedUrl);
    if (unsupportedPlaydropCaptureMessage) {
        throw new Error(`unsupported_playdrop_capture_target:${unsupportedPlaydropCaptureMessage}`);
    }
    const { username, password } = parseCredentialPair(options);
    return {
        targetUrl: trimmedUrl,
        expectedUrl,
        timeoutSeconds: parseTimeout(options.timeout),
        screenshotPath: (0, node_path_1.resolve)(process.cwd(), options.screenshot?.trim() || 'output/playwright/capture-url.png'),
        logPath: options.log?.trim() ? (0, node_path_1.resolve)(process.cwd(), options.log.trim()) : null,
        login: username
            ? {
                username,
                password,
                loginUrl: options.loginUrl?.trim() || null,
            }
            : null,
    };
}
async function captureRemote(url, options = {}) {
    let parsed;
    try {
        parsed = parseOptions(url, options);
    }
    catch (error) {
        if (error instanceof Error && error.message.startsWith('unsupported_playdrop_capture_target:')) {
            const detail = error.message.slice('unsupported_playdrop_capture_target:'.length).trim();
            (0, messages_1.printErrorWithHelp)(detail, [], { command: 'project capture remote' });
            process.exitCode = 1;
            return;
        }
        if (error instanceof Error && error.message === 'invalid_expected_url') {
            (0, messages_1.printErrorWithHelp)('The --expected-url value must be a valid URL.', [], { command: 'project capture remote' });
            process.exitCode = 1;
            return;
        }
        if (error instanceof Error && error.message === 'invalid_timeout') {
            (0, messages_1.printErrorWithHelp)('The --timeout value must be a number between 0 and 600 seconds.', [], { command: 'project capture remote' });
            process.exitCode = 1;
            return;
        }
        if (error instanceof Error && error.message === 'invalid_credentials_pair') {
            (0, messages_1.printErrorWithHelp)('Use --username and --password together.', [], { command: 'project capture remote' });
            process.exitCode = 1;
            return;
        }
        if (error instanceof Error && error.message === 'invalid_url') {
            (0, messages_1.printErrorWithHelp)('A valid URL is required.', ['Example: playdrop project capture remote https://www.playdrop.ai/creators/playdrop/apps/game/hangingout/play'], { command: 'project capture remote' });
            process.exitCode = 1;
            return;
        }
        (0, messages_1.printErrorWithHelp)('A URL is required.', ['Example: playdrop project capture remote https://www.playdrop.ai/creators/playdrop/apps/game/hangingout/play'], { command: 'project capture remote' });
        process.exitCode = 1;
        return;
    }
    await (0, commandContext_1.withEnvironment)('project capture remote', 'Capturing remote app logs', async ({ client, token }) => {
        let currentUser = null;
        try {
            currentUser = await (0, devShared_1.fetchDevUser)(client);
        }
        catch (error) {
            if (error instanceof http_1.CLIUnsupportedClientError) {
                return;
            }
            if (error instanceof types_1.UnsupportedClientError) {
                (0, http_1.handleUnsupportedError)(error, 'Authentication');
                process.exitCode = 1;
                return;
            }
            if (error instanceof types_1.ApiError) {
                (0, messages_1.printErrorWithHelp)(`Could not fetch your account (status ${error.status}).`, [
                    'Run "playdrop auth login" to refresh your session and ensure the API is reachable.',
                    'Use "playdrop auth whoami" afterwards to confirm your status.',
                ], { command: 'project capture remote' });
                process.exitCode = 1;
                return;
            }
            if ((0, devShared_1.isNetworkError)(error)) {
                (0, messages_1.printNetworkIssue)('Could not reach the Playdrop API to resolve your account.', 'project capture remote');
                process.exitCode = 1;
                return;
            }
            throw error;
        }
        console.log(`[capture] Launching Playwright against ${parsed.targetUrl}`);
        try {
            const result = await (0, captureRuntime_1.runCapture)({
                targetUrl: parsed.targetUrl,
                expectedUrl: parsed.expectedUrl ?? parsed.targetUrl,
                timeoutMs: Math.round(parsed.timeoutSeconds * 1000),
                minimumLogLevel: 'info',
                screenshotPath: parsed.screenshotPath,
                logPath: parsed.logPath,
                token: parsed.login ? undefined : token,
                user: parsed.login ? undefined : currentUser,
                login: parsed.login,
            });
            if (result.errorCount > 0) {
                console.error(`[capture] Completed with ${result.errorCount} error(s) after ${parsed.timeoutSeconds} seconds.`);
                process.exitCode = 1;
            }
            else {
                console.log(`[capture] Completed without console errors after ${parsed.timeoutSeconds} seconds.`);
            }
        }
        catch (error) {
            if (error instanceof http_1.CLIUnsupportedClientError) {
                return;
            }
            if (error instanceof types_1.UnsupportedClientError) {
                (0, http_1.handleUnsupportedError)(error, 'Capture');
                process.exitCode = 1;
                return;
            }
            if (error instanceof Error && error.stack) {
                console.error(error.stack);
            }
            else {
                console.error(error instanceof Error ? error.message : String(error));
            }
            process.exitCode = 1;
        }
    });
}
