"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.showBoostBalance = showBoostBalance;
exports.browseBoostOffers = browseBoostOffers;
exports.buyBoostPack = buyBoostPack;
exports.activateBoost = activateBoost;
exports.showBoostStatus = showBoostStatus;
exports.showBoostHistory = showBoostHistory;
exports.showBoostReport = showBoostReport;
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");
function parsePositiveInteger(raw, label, fallback) {
    if (raw === undefined) {
        return fallback;
    }
    const parsed = typeof raw === 'number' ? raw : Number.parseInt(String(raw), 10);
    if (!Number.isInteger(parsed) || parsed <= 0) {
        return null;
    }
    return parsed;
}
async function resolveAppForBoost(client, rawRef) {
    const ref = (0, refs_1.parseContentRef)(rawRef);
    if (ref.kind !== 'app') {
        throw new Error('invalid_app_ref');
    }
    const detail = await client.fetchAppBySlug(ref.creator, ref.name);
    return {
        ref,
        app: detail.app,
    };
}
function formatReportRow(row) {
    return [
        row.dateUtc,
        `impressions ${row.interstitialImpressions + row.rewardedImpressions}`,
        `views ${row.regularDetailViews} regular / ${row.promotedDetailViews} boosted`,
        `plays ${row.regularPlays} regular / ${row.promotedPlays} boosted`,
        `earnings ${row.adEarnings}`,
    ].join(' | ');
}
function formatRunDuration(startedAt, endsAt) {
    const totalHours = Math.max(1, Math.round((new Date(endsAt).getTime() - new Date(startedAt).getTime()) / (60 * 60 * 1000)));
    const days = Math.floor(totalHours / 24);
    const hours = totalHours % 24;
    if (days > 0 && hours > 0) {
        return `${days}d ${hours}h`;
    }
    if (days > 0) {
        return `${days}d`;
    }
    return `${hours}h`;
}
function formatUtcDate(value) {
    return value.toISOString().slice(0, 10);
}
function resolveReportRangeFromDays(days, now = new Date()) {
    const end = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
    const start = new Date(end.getTime() - ((days - 1) * 24 * 60 * 60 * 1000));
    return {
        startDateUtc: formatUtcDate(start),
        endDateUtc: formatUtcDate(end),
    };
}
async function showBoostBalance(options = {}) {
    await (0, commandContext_1.withEnvironment)('boosts balance', 'Checking your boost balance', async ({ client }) => {
        const response = await client.fetchBoostBalance();
        if (options.json) {
            (0, output_1.printJson)(response);
            return;
        }
        (0, output_1.printSuccess)(`Boost balance: ${response.balance}`, ['Next: run "playdrop boosts offers" or "playdrop boosts buy boost_1".']);
    });
}
async function browseBoostOffers(options = {}) {
    await (0, commandContext_1.withEnvironment)('boosts offers', 'Checking available boost packs', async ({ client }) => {
        const response = await client.fetchBoostBalance();
        if (options.json) {
            (0, output_1.printJson)({ offers: response.offers });
            return;
        }
        console.log('Boost offers:\n');
        for (const offer of response.offers) {
            console.log(`${offer.sku} | ${offer.units} units | ${offer.priceCredits} credits`);
        }
    });
}
async function buyBoostPack(sku, options = {}) {
    const normalizedSku = sku.trim().toLowerCase();
    if (!['boost_1', 'boost_3', 'boost_7', 'boost_14', 'boost_31'].includes(normalizedSku)) {
        (0, messages_1.printErrorWithHelp)('Boost SKU must be one of boost_1, boost_3, boost_7, boost_14, or boost_31.', ['Example: playdrop boosts buy boost_1'], { command: 'boosts buy' });
        process.exitCode = 1;
        return;
    }
    const quantity = parsePositiveInteger(options.quantity, 'quantity', 1);
    if (quantity === null) {
        (0, messages_1.printErrorWithHelp)('The --quantity value must be a positive integer.', ['Example: --quantity 2'], { command: 'boosts buy' });
        process.exitCode = 1;
        return;
    }
    await (0, commandContext_1.withEnvironment)('boosts buy', 'Buying boost pack', async ({ client }) => {
        try {
            const response = await client.purchaseBoostPack({ sku: normalizedSku, quantity });
            if (options.json) {
                (0, output_1.printJson)(response);
                return;
            }
            (0, output_1.printSuccess)(`Purchased ${response.offer.displayName}${response.quantity > 1 ? ` x ${response.quantity}` : ''}. Added ${response.unitsAdded} boost${response.unitsAdded === 1 ? '' : 's'}. Boost balance: ${response.boostBalance}. Credit balance: ${response.creditBalance}.`, ['Next: run "playdrop boosts activate <creator>/app/<name>".']);
        }
        catch (error) {
            const handled = (0, errors_1.handleCommandFailure)(error, 'boosts buy', 'Boost purchase', {
                apiMessage: (apiError) => ({
                    problem: `Boost purchase failed with status ${apiError.status}.`,
                    suggestions: ['Check your credit balance with "playdrop credits balance".'],
                }),
            });
            if (!handled) {
                throw error;
            }
        }
    });
}
async function activateBoost(rawRef, options = {}) {
    const units = parsePositiveInteger(options.units, 'units', 1);
    if (units === null) {
        (0, messages_1.printErrorWithHelp)('The --units value must be a positive integer.', ['Example: --units 2'], { command: 'boosts activate' });
        process.exitCode = 1;
        return;
    }
    await (0, commandContext_1.withEnvironment)('boosts activate', 'Activating boost', async ({ client }) => {
        const { app } = await resolveAppForBoost(client, rawRef);
        const response = await client.activateAppBoost(app.id, { units });
        if (options.json) {
            (0, output_1.printJson)(response);
            return;
        }
        (0, output_1.printSuccess)(`Boost active until ${response.boostedUntil ?? 'unknown'}. Remaining inventory: ${response.boostsAvailable}.`);
    });
}
async function showBoostStatus(rawRef, options = {}) {
    await (0, commandContext_1.withEnvironment)('boosts status', 'Checking boost status', async ({ client }) => {
        const { app } = await resolveAppForBoost(client, rawRef);
        const response = await client.fetchAppBoostStatus(app.id);
        if (options.json) {
            (0, output_1.printJson)(response);
            return;
        }
        console.log(`${response.app.displayName || response.app.name}`);
        console.log(`Status: ${response.isActive ? 'boosted' : 'inactive'}`);
        console.log(`Boosts available: ${response.boostsAvailable}`);
        console.log(`Boosted until: ${response.boostedUntil ?? 'none'}`);
        if (response.currentRun) {
            console.log(`Current run started: ${(0, output_1.formatTimestamp)(response.currentRun.startedAt)}`);
            console.log(`Current run ends: ${(0, output_1.formatTimestamp)(response.currentRun.endsAt)}`);
            console.log(`Current run units: ${response.currentRun.consumedUnits}`);
            console.log(`Current run impressions: ${response.currentRun.deliveredImpressionCount}`);
            console.log(`Current run views: ${response.currentRun.promotedDetailViewCount}`);
            console.log(`Current run plays: ${response.currentRun.promotedPlayCount}`);
        }
    });
}
async function showBoostHistory(rawRef, options = {}) {
    const limit = parsePositiveInteger(options.limit, 'limit', 30);
    if (limit === null) {
        (0, messages_1.printErrorWithHelp)('The --limit value must be a positive integer.', ['Example: --limit 20'], { command: 'boosts history' });
        process.exitCode = 1;
        return;
    }
    await (0, commandContext_1.withEnvironment)('boosts history', 'Checking boost history', async ({ client }) => {
        const { app } = await resolveAppForBoost(client, rawRef);
        const response = await client.fetchAppBoostHistory(app.id, { limit });
        if (options.json) {
            (0, output_1.printJson)(response);
            return;
        }
        if (response.runs.length === 0) {
            console.log('No boost runs found.');
            return;
        }
        console.log('Boost history:\n');
        for (const run of response.runs) {
            console.log(`#${run.id} | ${run.status.toLowerCase()} | ${(0, output_1.formatTimestamp)(run.startedAt)} -> ${(0, output_1.formatTimestamp)(run.endsAt)}`);
            console.log(`  duration ${formatRunDuration(run.startedAt, run.endsAt)} | units ${run.consumedUnits} | impressions ${run.deliveredImpressionCount} | views ${run.promotedDetailViewCount} | plays ${run.promotedPlayCount}`);
        }
    });
}
async function showBoostReport(rawRef, options = {}) {
    const days = parsePositiveInteger(options.days, 'days', 30);
    if (days === null) {
        (0, messages_1.printErrorWithHelp)('The --days value must be a positive integer.', ['Example: --days 30'], { command: 'boosts report' });
        process.exitCode = 1;
        return;
    }
    await (0, commandContext_1.withEnvironment)('boosts report', 'Checking boost report', async ({ client }) => {
        const { app } = await resolveAppForBoost(client, rawRef);
        const response = await client.fetchAppBoostReport(app.id, resolveReportRangeFromDays(days));
        if (options.json) {
            (0, output_1.printJson)(response);
            return;
        }
        console.log(`Boost report for ${app.displayName || app.name}:\n`);
        for (const row of response.days) {
            console.log(formatReportRow(row));
        }
    });
}
