"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 prompts_1 = require("../../lib/prompts");
function formatErrorMessage(error) {
    if (error instanceof Error)
        return error.message;
    if (typeof error === 'string')
        return error;
    try {
        return JSON.stringify(error);
    }
    catch {
        return 'Unknown error';
    }
}
class RepoConnect extends core_1.Command {
    async run() {
        const { args } = await this.parse(RepoConnect);
        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 });
        const target = args.repo ?? (await this.pickInteractively(api));
        if (!target) {
            console.log(chalk_1.default.dim('\n  Cancelled.\n'));
            return;
        }
        if (!/^[^/]+\/[^/]+$/.test(target)) {
            this.error(`Invalid repository name "${target}". Expected format: owner/repo`, { exit: 1 });
        }
        const spinner = (0, ora_1.default)(`Connecting ${chalk_1.default.bold(target)}…`).start();
        try {
            const result = await api.post('/repositories/import', {
                repositoryIds: [target],
            });
            this.handleImportResult(spinner, target, result);
        }
        catch (error) {
            spinner.fail('Failed to connect repository');
            this.printImportError(error);
            this.exit(1);
        }
    }
    handleImportResult(spinner, target, result) {
        const errors = result?.errors ?? [];
        const skipped = result?.skipped ?? 0;
        const imported = result?.imported ?? 0;
        if (errors.length > 0) {
            spinner.fail(`Could not connect ${target}`);
            for (const err of errors) {
                console.log(chalk_1.default.red(`  ${err}`));
            }
            console.log(chalk_1.default.dim('\n  If the repository is private or was just created, the GitHub App may not yet ' +
                'have access to it. Add it on github.com/settings/installations and retry.\n'));
            this.exit(1);
        }
        if (skipped > 0 && imported === 0) {
            spinner.succeed(`${target} was already connected`);
        }
        else {
            spinner.succeed(`Connected ${target}`);
        }
    }
    printImportError(error) {
        if (error instanceof api_client_1.ApiError && error.statusCode === 404) {
            console.log(chalk_1.default.yellow('\n  No active GitHub connection. Run `flui integration connect github` first.\n'));
            return;
        }
        const msg = formatErrorMessage(error);
        console.log(chalk_1.default.red(`  ${msg}`));
        if (msg.includes('Cannot read properties')) {
            console.log(chalk_1.default.dim('\n  Unexpected API response shape. Run `flui repo list` to check whether the ' +
                'repository was actually imported despite the error.\n'));
        }
    }
    async pickInteractively(api) {
        if (!process.stdin.isTTY) {
            this.error('Repository name is required in non-interactive mode. ' +
                'Pass it as an argument: `flui repo connect <owner/repo>`.', { exit: 1 });
        }
        const spinner = (0, ora_1.default)('Fetching repositories from GitHub…').start();
        let available;
        try {
            available = await api.get('/repositories/available');
            spinner.stop();
        }
        catch (error) {
            spinner.fail('Failed to fetch repositories');
            if (error instanceof api_client_1.ApiError && error.statusCode === 404) {
                console.log(chalk_1.default.yellow('\n  No active GitHub connection. Run `flui integration connect github` first.\n'));
            }
            else {
                console.log(chalk_1.default.red(`  ${error.message}`));
            }
            this.exit(1);
        }
        if (available.length === 0) {
            console.log(chalk_1.default.dim('\n  No repositories available to connect (all are already connected, ' +
                'or the GitHub App has no repos selected on its installation).\n'));
            return undefined;
        }
        const choice = await (0, prompts_1.selectWithArrows)(`Select a repository to connect:`, available.map((r) => ({
            label: `${r.fullName}${r.description ? chalk_1.default.dim(' — ' + r.description.slice(0, 60)) : ''}`,
        })));
        if (choice === -1)
            return undefined;
        return available[choice].fullName;
    }
}
RepoConnect.description = 'Connect (import) a GitHub repository into your Flui account so it can be deployed with `flui deploy`. ' +
    'Pass the full name `owner/repo`, or omit it for an interactive picker over the repositories accessible via your GitHub integration.';
RepoConnect.examples = [
    '<%= config.bin %> <%= command.id %> acme/my-app',
    '<%= config.bin %> <%= command.id %>',
];
RepoConnect.args = {
    repo: core_1.Args.string({
        description: 'Full repository name `owner/repo`. Omit to pick interactively.',
        required: false,
    }),
};
exports.default = RepoConnect;
