/**
 * GitHub Repository Selection Helper
 *
 * Implements US-011: Multi-Repo Selection Strategy for GitHub Init
 *
 * Provides functionality to:
 * - Detect user's GitHub organizations and personal repos
 * - Prompt for repository selection strategy (all org, all personal, pattern glob, pattern regex, explicit list)
 * - Filter repositories by pattern (glob or regex)
 * - Validate repository access
 * - Save selection to config
 */
import { select, input, confirm } from '@inquirer/prompts';
import chalk from 'chalk';
import { minimatch } from 'minimatch';
import { parsePatternShortcut, validateRegex } from './selection-strategy.js';
/**
 * Fetch user's organizations
 */
export async function fetchUserOrganizations(octokit) {
    try {
        const { data: orgs } = await octokit.orgs.listForAuthenticatedUser({
            per_page: 100
        });
        return orgs.map(org => org.login);
    }
    catch (error) {
        console.error(chalk.yellow('⚠️  Failed to fetch organizations:', error instanceof Error ? error.message : String(error)));
        return [];
    }
}
/**
 * Fetch all repositories for a specific organization (with pagination)
 */
export async function fetchOrgRepositories(octokit, org) {
    const repos = [];
    let page = 1;
    let hasMore = true;
    while (hasMore) {
        try {
            const { data } = await octokit.repos.listForOrg({
                org,
                per_page: 100,
                page
            });
            repos.push(...data);
            hasMore = data.length === 100; // GitHub returns 100 per page max
            page++;
        }
        catch (error) {
            console.error(chalk.yellow(`⚠️  Failed to fetch repos for org ${org}:`, error instanceof Error ? error.message : String(error)));
            hasMore = false;
        }
    }
    return repos;
}
/**
 * Fetch all personal repositories (owned by authenticated user)
 */
export async function fetchPersonalRepositories(octokit) {
    const repos = [];
    let page = 1;
    let hasMore = true;
    while (hasMore) {
        try {
            const { data } = await octokit.repos.listForAuthenticatedUser({
                affiliation: 'owner',
                per_page: 100,
                page
            });
            repos.push(...data);
            hasMore = data.length === 100;
            page++;
        }
        catch (error) {
            console.error(chalk.yellow('⚠️  Failed to fetch personal repos:', error instanceof Error ? error.message : String(error)));
            hasMore = false;
        }
    }
    return repos;
}
/**
 * Filter repositories by glob pattern
 */
export function filterRepositoriesByPattern(repos, pattern) {
    // Parse shortcuts (starts:, ends:, contains:)
    const parsedPattern = parsePatternShortcut(pattern);
    return repos.filter(repo => {
        // Match against repo name only
        return minimatch(repo.name, parsedPattern, { nocase: true });
    });
}
/**
 * Filter repositories by regex pattern
 */
export function filterRepositoriesByRegex(repos, pattern) {
    try {
        const regex = new RegExp(pattern, 'i'); // Case-insensitive
        const matched = repos.filter(repo => regex.test(repo.name));
        return { items: matched };
    }
    catch (error) {
        return {
            items: [],
            error: error instanceof Error ? error.message : String(error),
        };
    }
}
/**
 * Validate repository access (checks if user has at least read access)
 */
export async function validateRepositoryAccess(octokit, owner, repo) {
    try {
        await octokit.repos.get({ owner, repo });
        return true;
    }
    catch (error) {
        return false;
    }
}
/**
 * Show repository preview table
 */
export function showRepositoryPreview(repos) {
    console.log(chalk.blue('\n📋 Repository Preview:\n'));
    const header = `${chalk.bold('Repository')}${' '.repeat(40)}${chalk.bold('Owner')}${' '.repeat(15)}${chalk.bold('Visibility')}${' '.repeat(5)}${chalk.bold('Last Updated')}`;
    console.log(header);
    console.log('-'.repeat(100));
    repos.slice(0, 20).forEach(repo => {
        const repoName = repo.name.padEnd(45);
        const owner = repo.owner.login.padEnd(20);
        const visibility = (repo.private ? 'private' : 'public').padEnd(10);
        const lastUpdated = new Date(repo.updated_at).toLocaleDateString();
        console.log(`${repoName}${owner}${visibility}${lastUpdated}`);
    });
    if (repos.length > 20) {
        console.log(chalk.gray(`\n... and ${repos.length - 20} more repositories\n`));
    }
    else {
        console.log('');
    }
}
/**
 * Main repository selection flow
 */
export async function selectRepositories(octokit, githubToken) {
    console.log(chalk.blue('\n🔗 GitHub Multi-Repository Selection\n'));
    // Step 1: Detect organizations
    const orgs = await fetchUserOrganizations(octokit);
    // Step 2: Prompt for selection strategy - unified with ADO/JIRA
    const strategyChoices = [
        {
            name: `${chalk.green('✓')} All from organization ${chalk.gray('- Import all repos from an org')}`,
            value: 'all-org',
            disabled: orgs.length === 0 ? 'No organizations found' : false,
        },
        {
            name: `All personal ${chalk.gray('- Import all your personal repos')}`,
            value: 'all-personal',
        },
        {
            name: `Pattern (glob) ${chalk.gray('- Match by pattern (e.g., "ec-*", "*-backend")')}`,
            value: 'pattern-glob',
        },
        {
            name: `Pattern (regex) ${chalk.gray('- Regular expression (e.g., "^ec-.*$")')}`,
            value: 'pattern-regex',
        },
        {
            name: `Manual entry ${chalk.gray('- Enter repo names directly')}`,
            value: 'explicit',
        },
    ];
    const strategy = await select({
        message: 'How do you want to select repositories?',
        choices: strategyChoices,
        default: orgs.length > 0 ? 'all-org' : 'all-personal',
    });
    let selectedRepos = [];
    let selectionConfig = {
        repositories: [],
        selectionStrategy: strategy,
    };
    // Step 3: Execute strategy
    switch (strategy) {
        case 'all-org': {
            // Prompt to select organization
            const selectedOrg = await select({
                message: 'Select organization:',
                choices: orgs.map(org => ({ name: org, value: org })),
            });
            console.log(chalk.gray(`\n⏳ Fetching repositories from ${selectedOrg}...\n`));
            selectedRepos = await fetchOrgRepositories(octokit, selectedOrg);
            selectionConfig.organizationName = selectedOrg;
            break;
        }
        case 'all-personal': {
            console.log(chalk.gray('\n⏳ Fetching your personal repositories...\n'));
            selectedRepos = await fetchPersonalRepositories(octokit);
            break;
        }
        case 'pattern-glob': {
            // First, get source (org or personal)
            const sourceChoices = [
                { name: 'Personal repositories', value: 'personal' },
                ...orgs.map(org => ({ name: `Organization: ${org}`, value: `org:${org}` })),
            ];
            const source = await select({
                message: 'Select repository source:',
                choices: sourceChoices,
            });
            let allRepos = [];
            if (source === 'personal') {
                console.log(chalk.gray('\n⏳ Fetching your personal repositories...\n'));
                allRepos = await fetchPersonalRepositories(octokit);
            }
            else {
                const orgName = source.replace('org:', '');
                console.log(chalk.gray(`\n⏳ Fetching repositories from ${orgName}...\n`));
                allRepos = await fetchOrgRepositories(octokit, orgName);
                selectionConfig.organizationName = orgName;
            }
            // Show pattern hints
            console.log(chalk.gray('\n💡 Examples: "ec-*", "*-backend", "microservice-*"'));
            console.log(chalk.gray('💡 Shortcuts: "starts: ec-", "ends: -api", "contains: core"\n'));
            // Prompt for pattern
            const pattern = await input({
                message: 'Enter pattern:',
                validate: (value) => value.trim() ? true : 'Pattern is required',
            });
            selectedRepos = filterRepositoriesByPattern(allRepos, pattern.trim());
            selectionConfig.pattern = parsePatternShortcut(pattern.trim());
            if (selectedRepos.length === 0) {
                console.log(chalk.yellow(`\n⚠️  No repositories match pattern "${pattern}"\n`));
                const retry = await confirm({
                    message: 'Try a different pattern?',
                    default: true,
                });
                if (retry) {
                    return selectRepositories(octokit, githubToken);
                }
                return null;
            }
            break;
        }
        case 'pattern-regex': {
            // First, get source (org or personal)
            const sourceChoices = [
                { name: 'Personal repositories', value: 'personal' },
                ...orgs.map(org => ({ name: `Organization: ${org}`, value: `org:${org}` })),
            ];
            const source = await select({
                message: 'Select repository source:',
                choices: sourceChoices,
            });
            let allRepos = [];
            if (source === 'personal') {
                console.log(chalk.gray('\n⏳ Fetching your personal repositories...\n'));
                allRepos = await fetchPersonalRepositories(octokit);
            }
            else {
                const orgName = source.replace('org:', '');
                console.log(chalk.gray(`\n⏳ Fetching repositories from ${orgName}...\n`));
                allRepos = await fetchOrgRepositories(octokit, orgName);
                selectionConfig.organizationName = orgName;
            }
            // Show regex hints
            console.log(chalk.gray('\n💡 Examples: "^ec-", ".*-backend$", "^microservice-\\d+$"\n'));
            // Prompt for regex pattern
            const pattern = await input({
                message: 'Enter regex pattern:',
                validate: (value) => {
                    if (!value.trim())
                        return 'Pattern is required';
                    const validation = validateRegex(value.trim());
                    if (validation !== true) {
                        return `Invalid regular expression: ${validation}`;
                    }
                    return true;
                },
            });
            const regexResult = filterRepositoriesByRegex(allRepos, pattern.trim());
            if (regexResult.error) {
                console.log(chalk.red(`\n❌ Invalid regex: ${regexResult.error}\n`));
                return null;
            }
            selectedRepos = regexResult.items;
            selectionConfig.pattern = pattern.trim();
            selectionConfig.isRegex = true;
            if (selectedRepos.length === 0) {
                console.log(chalk.yellow(`\n⚠️  No repositories match regex "${pattern}"\n`));
                const retry = await confirm({
                    message: 'Try a different pattern?',
                    default: true,
                });
                if (retry) {
                    return selectRepositories(octokit, githubToken);
                }
                return null;
            }
            break;
        }
        case 'explicit': {
            console.log(chalk.gray('\n💡 Enter repository names separated by commas'));
            console.log(chalk.gray('💡 Example: "repo1, repo2, repo3"\n'));
            const repoList = await input({
                message: 'Enter repository names (comma-separated):',
                validate: (value) => value.trim() ? true : 'At least one repository is required',
            });
            const repoNames = repoList.split(',').map(s => s.trim()).filter(Boolean);
            // Fetch authenticated user to get owner name
            const { data: user } = await octokit.users.getAuthenticated();
            const owner = user.login;
            // Validate each repository
            console.log(chalk.gray('\n⏳ Validating repository access...\n'));
            for (const repoName of repoNames) {
                try {
                    const { data: repo } = await octokit.repos.get({ owner, repo: repoName });
                    selectedRepos.push(repo);
                }
                catch (error) {
                    console.log(chalk.yellow(`⚠️  Cannot access repository: ${repoName}`));
                }
            }
            if (selectedRepos.length === 0) {
                console.log(chalk.red('\n❌ No accessible repositories found\n'));
                return null;
            }
            break;
        }
    }
    // Step 4: Show preview and confirm
    showRepositoryPreview(selectedRepos);
    const confirmed = await confirm({
        message: `Connect these ${selectedRepos.length} repositories?`,
        default: true,
    });
    if (!confirmed) {
        console.log(chalk.gray('\n✓ Repository selection cancelled\n'));
        return null;
    }
    // Step 5: Build final configuration
    selectionConfig.repositories = selectedRepos.map(repo => repo.full_name);
    console.log(chalk.green(`\n✅ Selected ${selectionConfig.repositories.length} repositories\n`));
    return selectionConfig;
}
//# sourceMappingURL=github-repo-selector.js.map