"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detail = detail;
const commandContext_1 = require("../commandContext");
const errors_1 = require("../errors");
const messages_1 = require("../messages");
const output_1 = require("../output");
const refs_1 = require("../refs");
const appUrls_1 = require("../appUrls");
function printRefValidationError(raw) {
    (0, messages_1.printErrorWithHelp)('A canonical ref is required.', [
        'Use the format <creator>/<kind>/<name>.',
        'Kinds must be exactly app, asset, asset-spec, or asset-pack.',
        `Example: playdrop detail playdrop/app/hangingout`,
        `Example: playdrop detail playdrop/asset/astro`,
    ], { command: 'detail' });
    process.exitCode = 1;
}
function buildAssetSourceUrl(apiBase, ref, revision) {
    const encodedCreator = encodeURIComponent(ref.creator);
    const encodedName = encodeURIComponent(ref.name);
    return `${apiBase}/assets/${encodedCreator}/${encodedName}/versions/${revision}/source`;
}
function resolveAppSourceUrl(apiBase, sourceUrl) {
    const trimmed = typeof sourceUrl === 'string' ? sourceUrl.trim() : '';
    if (!trimmed) {
        return null;
    }
    return new URL(trimmed, apiBase).toString();
}
function buildAssetPackSourceUrl(apiBase, ref, version) {
    const encodedCreator = encodeURIComponent(ref.creator);
    const encodedName = encodeURIComponent(ref.name);
    const encodedVersion = encodeURIComponent(version);
    return `${apiBase}/asset-packs/${encodedCreator}/${encodedName}/versions/${encodedVersion}/source`;
}
function buildAssetPackDownloadUrl(apiBase, ref, version) {
    const encodedCreator = encodeURIComponent(ref.creator);
    const encodedName = encodeURIComponent(ref.name);
    const encodedVersion = encodeURIComponent(version);
    return `${apiBase}/asset-packs/${encodedCreator}/${encodedName}/versions/${encodedVersion}/download`;
}
function extractAssetFileUrls(asset) {
    const files = asset.currentVersion?.fileManifest?.files;
    if (!Array.isArray(files)) {
        return [];
    }
    return files
        .filter((entry) => typeof entry?.role === 'string' && typeof entry?.url === 'string' && entry.url.trim().length > 0)
        .map((entry) => ({ role: entry.role, url: entry.url.trim() }));
}
function decorateApp(app, apiBase, webBase, dependencies) {
    return {
        ...app,
        dependencies,
        urls: {
            play: (0, appUrls_1.buildPlatformPlayUrl)(webBase, {
                creatorUsername: app.creatorUsername,
                appName: app.name,
                appType: app.type,
            }),
            source: resolveAppSourceUrl(apiBase, app.sourceUrl),
        },
    };
}
function decorateAsset(apiBase, ref, asset) {
    return {
        ...asset,
        urls: {
            source: asset.currentVersion ? buildAssetSourceUrl(apiBase, ref, asset.currentVersion.revision) : null,
            files: extractAssetFileUrls(asset),
        },
    };
}
function decorateAssetPack(apiBase, ref, pack) {
    return {
        ...pack,
        urls: {
            download: pack.currentVersion?.version ? buildAssetPackDownloadUrl(apiBase, ref, pack.currentVersion.version) : null,
            source: pack.currentVersion?.version ? buildAssetPackSourceUrl(apiBase, ref, pack.currentVersion.version) : null,
        },
    };
}
function formatTagSummary(tags) {
    const normalizedTags = Array.isArray(tags) ? tags : [];
    if (normalizedTags.length === 0) {
        return 'none';
    }
    return normalizedTags.map((tag) => `${tag.ref} (${tag.displayName})`).join(', ');
}
function printAppDependencyLines(label, items) {
    if (items.length === 0) {
        console.log(`${label}: none`);
        return;
    }
    console.log(`${label}:`);
    for (const item of items) {
        console.log(`- ${item}`);
    }
}
function printAppText(ref, app) {
    console.log(`[app] ${ref}`);
    console.log(`Display name: ${(0, output_1.formatOptionalValue)(app.displayName)}`);
    console.log(`Creator: @${app.creatorUsername}`);
    console.log(`Type: ${app.type.toLowerCase()}`);
    console.log(`Description: ${(0, output_1.formatOptionalValue)(app.description)}`);
    console.log(`Created: ${(0, output_1.formatTimestamp)(app.createdAt)}`);
    console.log(`Updated: ${(0, output_1.formatTimestamp)(app.updatedAt)}`);
    console.log(`Current version: ${(0, output_1.formatOptionalValue)(app.currentVersion)}`);
    console.log(`Tags: ${formatTagSummary(app.tags)}`);
    console.log(`Owned assets: ${app.dependencies?.ownedAssets.length ?? 0}`);
    console.log(`Direct assets: ${app.dependencies?.directAssets.length ?? 0}`);
    console.log(`Packs: ${app.dependencies?.packs.length ?? 0}`);
    printAppDependencyLines('Registered assets', (app.dependencies?.ownedAssets ?? []).map((item) => {
        const runtimeKey = typeof item.runtimeKey === 'string' && item.runtimeKey.trim().length > 0
            ? `runtimeKey=${item.runtimeKey} `
            : '';
        return `${runtimeKey}${item.assetRef}`;
    }));
    printAppDependencyLines('Linked assets', (app.dependencies?.directAssets ?? []).map((item) => item.assetRef));
    printAppDependencyLines('Linked packs', (app.dependencies?.packs ?? []).map((item) => item.packRef));
    console.log(`Play URL: ${(0, output_1.formatOptionalValue)(app.urls.play)}`);
    console.log(`Source URL: ${(0, output_1.formatOptionalValue)(app.urls.source)}`);
    console.log('\nNext: run "playdrop versions browse ' + ref + '" to inspect version history.');
}
function printAssetText(ref, asset) {
    console.log(`[asset] ${ref}`);
    console.log(`Display name: ${(0, output_1.formatOptionalValue)(asset.displayName)}`);
    console.log(`Creator: @${asset.creatorUsername}`);
    console.log(`Category: ${asset.category.toLowerCase()}`);
    console.log(`Description: ${(0, output_1.formatOptionalValue)(asset.description)}`);
    console.log(`Created: ${(0, output_1.formatTimestamp)(asset.createdAt)}`);
    console.log(`Updated: ${(0, output_1.formatTimestamp)(asset.updatedAt)}`);
    console.log(`Current revision: ${asset.currentVersion ? asset.currentVersion.revisionLabel : 'none'}`);
    console.log(`Current subcategory: ${(0, output_1.formatOptionalValue)(asset.currentVersion?.subcategory)}`);
    console.log(`Tags: ${formatTagSummary(asset.tags)}`);
    console.log(`Source URL: ${(0, output_1.formatOptionalValue)(asset.urls.source)}`);
    if (asset.urls.files.length > 0) {
        for (const file of asset.urls.files) {
            console.log(`File URL (${file.role}): ${file.url}`);
        }
    }
    else {
        console.log('File URLs: none');
    }
    console.log('\nNext: run "playdrop versions browse ' + ref + '" to inspect other revisions.');
}
function printAssetPackText(ref, pack) {
    console.log(`[asset-pack] ${ref}`);
    console.log(`Display name: ${(0, output_1.formatOptionalValue)(pack.displayName)}`);
    console.log(`Creator: @${pack.creatorUsername}`);
    console.log(`Description: ${(0, output_1.formatOptionalValue)(pack.description)}`);
    console.log(`Created: ${(0, output_1.formatTimestamp)(pack.createdAt)}`);
    console.log(`Updated: ${(0, output_1.formatTimestamp)(pack.updatedAt)}`);
    console.log(`Current version: ${(0, output_1.formatOptionalValue)(pack.currentVersion?.version)}`);
    console.log(`Tags: ${formatTagSummary(pack.tags)}`);
    console.log(`Download URL: ${(0, output_1.formatOptionalValue)(pack.urls.download)}`);
    console.log(`Source URL: ${(0, output_1.formatOptionalValue)(pack.urls.source)}`);
    console.log('\nNext: run "playdrop versions browse ' + ref + '" to inspect other versions.');
}
function printAssetSpecText(ref, assetSpec) {
    console.log(`[asset-spec] ${ref}`);
    console.log(`Display name: ${(0, output_1.formatOptionalValue)(assetSpec.displayName)}`);
    console.log(`Creator: @${assetSpec.creatorUsername}`);
    console.log(`Description: ${(0, output_1.formatOptionalValue)(assetSpec.description)}`);
    console.log(`Current version: ${(0, output_1.formatOptionalValue)(assetSpec.currentVersion?.version)}`);
    console.log(`Status: ${(0, output_1.formatOptionalValue)(assetSpec.status)}`);
    console.log(`Public assets: ${assetSpec.publicAssetCount.toLocaleString('en-US')}`);
    console.log(`Supporting apps: ${assetSpec.supportingAppCount.toLocaleString('en-US')}`);
    console.log(`Documentation: ${assetSpec.documentationAvailable ? 'available' : 'none'}`);
    console.log(`Created: ${(0, output_1.formatTimestamp)(assetSpec.createdAt)}`);
    console.log(`Updated: ${(0, output_1.formatTimestamp)(assetSpec.updatedAt)}`);
    console.log('\nNext: run "playdrop versions browse ' + ref + '" to inspect version history.');
}
async function detail(rawRef, options = {}) {
    let ref;
    try {
        ref = (0, refs_1.parseContentRef)(rawRef ?? '');
    }
    catch {
        printRefValidationError(rawRef);
        return;
    }
    await (0, commandContext_1.withPublicEnvironment)('detail', async ({ client, envConfig }) => {
        try {
            if (ref.kind === 'app') {
                const response = await client.fetchAppBySlug(ref.creator, ref.name, { includeDependencies: true });
                const item = decorateApp(response.app, envConfig.apiBase, envConfig.webBase, response.dependencies);
                if (options.json) {
                    (0, output_1.printJson)({ kind: ref.kind, ref: ref.ref, item });
                    return;
                }
                printAppText(ref.ref, item);
                return;
            }
            if (ref.kind === 'asset') {
                const response = await client.fetchAssetBySlug(ref.creator, ref.name);
                const item = decorateAsset(envConfig.apiBase, ref, response.asset);
                if (options.json) {
                    (0, output_1.printJson)({ kind: ref.kind, ref: ref.ref, item });
                    return;
                }
                printAssetText(ref.ref, item);
                return;
            }
            if (ref.kind === 'asset-pack') {
                const response = await client.fetchAssetPackBySlug(ref.creator, ref.name);
                const item = decorateAssetPack(envConfig.apiBase, ref, response.pack);
                if (options.json) {
                    (0, output_1.printJson)({ kind: ref.kind, ref: ref.ref, item });
                    return;
                }
                printAssetPackText(ref.ref, item);
                return;
            }
            const response = await client.fetchAssetSpecBySlug(ref.creator, ref.name);
            const item = response.assetSpec;
            if (options.json) {
                (0, output_1.printJson)({ kind: ref.kind, ref: ref.ref, item });
                return;
            }
            printAssetSpecText(ref.ref, item);
        }
        catch (error) {
            const handled = (0, errors_1.handleCommandFailure)(error, 'detail', 'Detail lookup', {
                apiMessage: (apiError) => {
                    if (apiError.status === 404) {
                        return {
                            problem: `No item was found for "${ref.ref}".`,
                            suggestions: ['Check the ref and retry.', 'Run "playdrop browse" to explore available content.'],
                        };
                    }
                    if (apiError.status === 401 || apiError.status === 403) {
                        return {
                            problem: `You do not have access to "${ref.ref}".`,
                            suggestions: ['Run "playdrop auth login" if this is private content you own.', 'Use "playdrop help detail" for the ref format.'],
                        };
                    }
                    return {
                        problem: `Detail lookup failed with status ${apiError.status}.`,
                        suggestions: ['Retry in a moment.', 'Use "playdrop help detail" for usage details.'],
                    };
                },
            });
            if (!handled) {
                throw error;
            }
        }
    });
}
