"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const api_client_1 = require("../../../lib/api-client");
const config_storage_1 = require("../../../lib/config-storage");
const browser_callback_1 = require("../../../lib/browser-callback");
const prompts_1 = require("../../../lib/prompts");
const PAT_PATTERN = /^(ghp_|github_pat_)/;
const DEFAULT_EXPIRY_DAYS = 90;
class IntegrationGhcrPatSet extends core_1.Command {
    async run() {
        const { flags } = await this.parse(IntegrationGhcrPatSet);
        const configStorage = new config_storage_1.ConfigStorage();
        const apiUrl = configStorage.getApiUrlOrThrow();
        const apiKey = configStorage.getApiKey();
        if (!apiKey) {
            this.error('Not logged in. Run `flui auth login` first.', { exit: 1 });
        }
        const api = new api_client_1.ApiClient({ baseUrl: apiUrl, apiKey });
        let existing = null;
        try {
            existing = await api.get('/repositories/github-app/packages-pat/status');
        }
        catch {
            /* empty */
        }
        this.printInstructions(existing?.configured ?? false, flags.headless);
        const token = await (0, prompts_1.promptMaskedInput)('Token');
        if (!token) {
            this.error('Token cannot be empty', { exit: 1 });
        }
        if (!PAT_PATTERN.test(token)) {
            this.error('Token must start with `ghp_` (classic PAT) or `github_pat_` (fine-grained PAT).', { exit: 1 });
        }
        const defaultExpiry = new Date(Date.now() + DEFAULT_EXPIRY_DAYS * 24 * 60 * 60 * 1000)
            .toISOString()
            .slice(0, 10);
        const expiry = await (0, prompts_1.promptInput)({
            message: 'Expiry date (YYYY-MM-DD, must match the one set on GitHub)',
            default: defaultExpiry,
            validate: (v) => {
                if (!/^\d{4}-\d{2}-\d{2}$/.test(v))
                    return 'Expected format YYYY-MM-DD';
                const d = new Date(v);
                if (Number.isNaN(d.getTime()))
                    return 'Not a valid date';
                if (d.getTime() < Date.now())
                    return 'Expiry must be in the future';
                return null;
            },
        });
        const expiresAt = new Date(`${expiry}T00:00:00.000Z`).toISOString();
        const action = existing?.configured ? 'Rotating' : 'Saving';
        const endpoint = existing?.configured
            ? '/repositories/github-app/packages-pat/rotate'
            : '/repositories/github-app/packages-pat';
        const method = existing?.configured ? 'put' : 'post';
        const spinner = (0, ora_1.default)(`${action} GHCR PAT…`).start();
        try {
            const result = await api[method](endpoint, {
                token,
                expiresAt,
            });
            spinner.succeed(`${action.replace(/ing$/, 'ed')} GHCR PAT`);
            this.printResult(result);
        }
        catch (error) {
            spinner.fail(`Failed to ${action.toLowerCase()} GHCR PAT`);
            this.printSaveError(error);
            this.exit(1);
        }
    }
    printResult(result) {
        console.log('');
        if (result.githubLogin) {
            console.log(`  GitHub user: ${chalk_1.default.bold(result.githubLogin)}`);
        }
        if (result.scopes && result.scopes.length > 0) {
            console.log(`  Scopes:      ${result.scopes.join(', ')}`);
        }
        if (result.expiresAt) {
            console.log(`  Expires:     ${new Date(result.expiresAt).toISOString().slice(0, 10)}`);
        }
        console.log('');
        console.log(chalk_1.default.dim('  You can now `flui deploy`. Set a calendar reminder to rotate before expiry.'));
        console.log('');
    }
    printSaveError(error) {
        if (error instanceof api_client_1.ApiError && error.statusCode === 400) {
            console.log(chalk_1.default.red(`  ${error.message}`));
            console.log(chalk_1.default.yellow('  GitHub rejected the token. Check it has read:packages scope and is not expired.'));
            return;
        }
        console.log(chalk_1.default.red(`  ${error.message}`));
    }
    printInstructions(alreadyConfigured, headless) {
        const prefilledUrl = 'https://github.com/settings/tokens/new?scopes=read:packages,delete:packages&description=Flui+GHCR+pull';
        console.log('');
        if (alreadyConfigured) {
            console.log(chalk_1.default.yellow('  A GHCR PAT is already configured. This will replace it.'));
            console.log('');
        }
        console.log(`  ${chalk_1.default.bold('Generate a GitHub Personal Access Token (classic)')}`);
        console.log('');
        const opened = !headless && (0, browser_callback_1.openInBrowser)(prefilledUrl);
        if (opened) {
            console.log(chalk_1.default.dim('  Opened browser at the token-creation page.'));
            console.log(chalk_1.default.dim('  If it did not open, use this URL:'));
            console.log(`  ${chalk_1.default.cyan(prefilledUrl)}`);
        }
        else {
            console.log(`  Pre-filled link (scopes already set):`);
            console.log(`  ${chalk_1.default.cyan(prefilledUrl)}`);
        }
        console.log('');
        console.log(`  Required scopes: ${chalk_1.default.bold('read:packages')} ${chalk_1.default.dim('(or write:packages)')}`);
        console.log(`  Recommended:     ${chalk_1.default.bold('delete:packages')} ${chalk_1.default.dim('(lets Flui clean up old images)')}`);
        console.log(`  Expiry:          ${chalk_1.default.dim('pick a date (90 days is a sensible default)')}`);
        console.log('');
        console.log(chalk_1.default.dim('  Fine-grained PATs (github_pat_…) are also accepted as long as'));
        console.log(chalk_1.default.dim('  they grant Packages: read on the relevant org/account.'));
        console.log('');
    }
}
IntegrationGhcrPatSet.description = 'Save (or replace) the GitHub classic PAT used by Flui to pull container images from GHCR. Required for `flui deploy` to work — GitHub App and OAuth tokens cannot read container packages (see https://github.com/orgs/community/discussions/34084).';
IntegrationGhcrPatSet.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> --headless',
];
IntegrationGhcrPatSet.flags = {
    headless: core_1.Flags.boolean({
        description: 'Print the GitHub token-creation URL instead of opening a browser (useful over SSH)',
        default: false,
    }),
};
exports.default = IntegrationGhcrPatSet;
