/**
 * Vigthoria CLI - Repo Commands
 *
 * Push and pull projects to/from Vigthoria Repository
 * Enables version control and project sharing through the Vigthoria platform
 *
 * Usage:
 *   vigthoria repo push [path]     - Push current/specified project to Vigthoria Repo
 *   vigthoria repo pull <name>     - Pull a project from your Vigthoria Repo
 *   vigthoria repo list            - List all your projects in Vigthoria Repo
 *   vigthoria repo status          - Show sync status of current project
 *   vigthoria repo share <name>    - Generate shareable link for a project
 *   vigthoria repo delete <name>   - Remove a project from your Vigthoria Repo
 */
import chalk from 'chalk';
import * as fs from 'fs';
import * as path from 'path';
import { createRequire } from 'node:module';
import { createSpinner, CH } from '../utils/logger.js';
const require = createRequire(import.meta.url);
import inquirer from 'inquirer';
import archiver from 'archiver';
import { createWriteStream } from 'fs';
export class RepoCommand {
    config;
    logger;
    apiBase;
    communityBase;
    communityToken;
    constructor(config, logger) {
        this.config = config;
        this.logger = logger;
        this.apiBase = this.config.get('apiUrl') || 'https://coder.vigthoria.io';
        this.communityBase = process.env.VIGTHORIA_COMMUNITY_API_URL || 'https://community.vigthoria.io';
        this.communityToken = process.env.VIGTHORIA_COMMUNITY_TOKEN || null;
    }
    getAuthHeaders() {
        const token = this.communityToken || this.config.get('authToken');
        return {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
        };
    }
    async ensureCommunityAuth() {
        if (this.communityToken) {
            return;
        }
        const email = process.env.VIGTHORIA_COMMUNITY_EMAIL;
        const password = process.env.VIGTHORIA_COMMUNITY_PASSWORD;
        if (!email || !password) {
            return;
        }
        const response = await fetch(`${this.communityBase}/api/auth/login`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ email, password })
        });
        const data = await response.json();
        if (!response.ok || !data.token) {
            throw new Error(data.error || data.message || 'Community login failed');
        }
        this.communityToken = data.token;
    }
    async repoFetch(apiPath, init = {}) {
        const normalizedApiPath = apiPath.startsWith('/api/repo') ? apiPath : `/api/repo${apiPath.startsWith('/') ? apiPath : `/${apiPath}`}`;
        const proxyPath = `${this.apiBase}/api/community-repo${normalizedApiPath.replace('/api/repo', '')}`;
        const directPath = `${this.communityBase}${normalizedApiPath}`;
        const attempt = async (url, allowCommunityAuthRetry) => {
            const response = await fetch(url, {
                ...init,
                headers: {
                    ...this.getAuthHeaders(),
                    ...(init.headers || {})
                }
            });
            if (response.status === 401 && allowCommunityAuthRetry && !this.communityToken) {
                await this.ensureCommunityAuth();
                if (this.communityToken) {
                    return attempt(url, false);
                }
            }
            return response;
        };
        try {
            const proxyResponse = await attempt(proxyPath, true);
            if (proxyResponse.ok || proxyResponse.status < 500) {
                return proxyResponse;
            }
        }
        catch {
            // fall through to direct community endpoint
        }
        return attempt(directPath, true);
    }
    collectProjectFiles(projectPath) {
        const files = [];
        const ignoreNames = new Set(['node_modules', '.git', 'dist', 'build', '__pycache__', '.venv', 'venv']);
        const ignoreSuffixes = ['.log'];
        const walk = (dir) => {
            for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
                if (ignoreNames.has(entry.name) || entry.name.startsWith('.')) {
                    continue;
                }
                const fullPath = path.join(dir, entry.name);
                const relativePath = path.relative(projectPath, fullPath);
                if (entry.isDirectory()) {
                    walk(fullPath);
                    continue;
                }
                if (!entry.isFile() || ignoreSuffixes.some((suffix) => entry.name.endsWith(suffix))) {
                    continue;
                }
                try {
                    files.push({
                        path: relativePath,
                        content: fs.readFileSync(fullPath, 'utf8')
                    });
                }
                catch {
                    // Skip binary or unreadable files.
                }
            }
        };
        walk(projectPath);
        return files;
    }
    async getMyRepos() {
        const response = await this.repoFetch('/api/repo/my-repos', {
            method: 'GET'
        });
        if (!response.ok) {
            const error = await response.json().catch(async () => ({ error: await response.text() }));
            throw new Error(error.error || error.message || 'Failed to fetch repositories');
        }
        const data = await response.json();
        return data.repos || data.projects || [];
    }
    async resolveRepoByName(projectName) {
        const repos = await this.getMyRepos();
        const normalized = projectName.trim().toLowerCase();
        const exactMatch = repos.find((repo) => {
            const name = String(repo.name || repo.project_name || '').trim().toLowerCase();
            return name === normalized || String(repo.id) === projectName.trim();
        });
        const match = exactMatch || repos.find((repo) => {
            const name = String(repo.name || repo.project_name || '').trim().toLowerCase();
            return name.includes(normalized);
        });
        if (!match) {
            throw new Error(`Repository not found: ${projectName}`);
        }
        return match;
    }
    formatRepoError(error) {
        const message = error instanceof Error ? error.message : 'Unknown error';
        if (/invalid or expired session/i.test(message)) {
            return 'Repo memory service is not deployed or not reachable. Check `vigthoria status` for details.';
        }
        if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|socket hang up/i.test(message)) {
            return 'Repo memory service is not reachable. Check `vigthoria status` for details.';
        }
        return message;
    }
    isAuthenticated() {
        const token = this.config.get('authToken');
        return !!token;
    }
    requireAuth() {
        if (!this.isAuthenticated()) {
            console.log(chalk.red('\n❌ Authentication required. Run: vigthoria login\n'));
            process.exit(1);
        }
    }
    /**
     * Detect project info from package.json, requirements.txt, etc.
     */
    detectProjectInfo(projectPath) {
        let name = path.basename(projectPath);
        let description = '';
        const techStack = [];
        // Check package.json (Node.js)
        const packageJsonPath = path.join(projectPath, 'package.json');
        if (fs.existsSync(packageJsonPath)) {
            try {
                const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
                name = pkg.name || name;
                description = pkg.description || '';
                techStack.push('Node.js');
                // Detect frameworks from dependencies
                const deps = { ...pkg.dependencies, ...pkg.devDependencies };
                if (deps.express)
                    techStack.push('Express');
                if (deps.react)
                    techStack.push('React');
                if (deps.vue)
                    techStack.push('Vue');
                if (deps.next)
                    techStack.push('Next.js');
                if (deps.typescript)
                    techStack.push('TypeScript');
                if (deps.sqlite3 || deps['better-sqlite3'])
                    techStack.push('SQLite');
                if (deps.stripe)
                    techStack.push('Stripe');
            }
            catch (e) {
                // Ignore parse errors
            }
        }
        // Check requirements.txt (Python)
        const requirementsPath = path.join(projectPath, 'requirements.txt');
        if (fs.existsSync(requirementsPath)) {
            techStack.push('Python');
            const content = fs.readFileSync(requirementsPath, 'utf8').toLowerCase();
            if (content.includes('flask'))
                techStack.push('Flask');
            if (content.includes('django'))
                techStack.push('Django');
            if (content.includes('fastapi'))
                techStack.push('FastAPI');
            if (content.includes('torch') || content.includes('pytorch'))
                techStack.push('PyTorch');
            if (content.includes('tensorflow'))
                techStack.push('TensorFlow');
        }
        // Check Cargo.toml (Rust)
        if (fs.existsSync(path.join(projectPath, 'Cargo.toml'))) {
            techStack.push('Rust');
        }
        // Check go.mod (Go)
        if (fs.existsSync(path.join(projectPath, 'go.mod'))) {
            techStack.push('Go');
        }
        return { name, description, techStack: [...new Set(techStack)] };
    }
    /**
     * Create a zip archive of a project
     */
    async createProjectArchive(projectPath) {
        const tempDir = path.join(require('os').tmpdir(), 'vigthoria-cli');
        if (!fs.existsSync(tempDir)) {
            fs.mkdirSync(tempDir, { recursive: true });
        }
        const archivePath = path.join(tempDir, `project-${Date.now()}.zip`);
        const output = createWriteStream(archivePath);
        const archive = archiver('zip', { zlib: { level: 9 } });
        return new Promise((resolve, reject) => {
            output.on('close', () => resolve(archivePath));
            archive.on('error', (err) => reject(err));
            archive.pipe(output);
            // Ignore patterns
            const ignorePatterns = [
                'node_modules/**',
                '.git/**',
                'dist/**',
                'build/**',
                '__pycache__/**',
                '.venv/**',
                'venv/**',
                '*.log',
                '.env',
                '.DS_Store'
            ];
            archive.glob('**/*', {
                cwd: projectPath,
                ignore: ignorePatterns,
                dot: true
            });
            archive.finalize();
        });
    }
    /**
     * Push a project to Vigthoria Repository
     */
    async push(options = {}) {
        this.requireAuth();
        const projectPath = options.path ? path.resolve(options.path) : process.cwd();
        if (!fs.existsSync(projectPath)) {
            console.log(chalk.red(`\n❌ Path does not exist: ${projectPath}\n`));
            return;
        }
        const spinner = createSpinner('Analyzing project...').start();
        try {
            const projectInfo = this.detectProjectInfo(projectPath);
            spinner.succeed(`Project detected: ${chalk.cyan(projectInfo.name)}`);
            console.log(chalk.gray(`\n  📁 Path: ${projectPath}`));
            console.log(chalk.gray(`  📝 Description: ${projectInfo.description || '(none)'}`));
            console.log(chalk.gray(`  🔧 Tech Stack: ${projectInfo.techStack.join(', ') || 'Unknown'}`));
            console.log();
            const defaults = {
                name: options.name || projectInfo.name,
                description: options.description || projectInfo.description,
                visibility: options.visibility || 'private'
            };
            const answers = options.yes
                ? { ...defaults, confirm: true }
                : await inquirer.prompt([
                    {
                        type: 'input',
                        name: 'name',
                        message: 'Project name:',
                        default: defaults.name
                    },
                    {
                        type: 'input',
                        name: 'description',
                        message: 'Description:',
                        default: defaults.description
                    },
                    {
                        type: 'list',
                        name: 'visibility',
                        message: 'Visibility:',
                        choices: [
                            { name: 'Private - Only you can access', value: 'private' },
                            { name: 'Restricted - Invite only', value: 'restricted' },
                            { name: 'Public - Anyone can view', value: 'public' }
                        ],
                        default: defaults.visibility
                    },
                    {
                        type: 'confirm',
                        name: 'confirm',
                        message: 'Push project to Vigthoria Repo?',
                        default: true
                    }
                ]);
            if (!answers.confirm) {
                console.log(chalk.yellow(`\n${CH.warnEmoji}  Push cancelled.\n`));
                return;
            }
            const uploadSpinner = createSpinner('Preparing project files...').start();
            const files = this.collectProjectFiles(projectPath);
            if (files.length === 0) {
                throw new Error('No readable text files found to push');
            }
            uploadSpinner.text = 'Uploading to Vigthoria Community...';
            const registerResponse = await this.repoFetch('/api/repo/push', {
                method: 'POST',
                body: JSON.stringify({
                    projectName: answers.name,
                    description: answers.description,
                    techStack: projectInfo.techStack.join(', '),
                    visibility: answers.visibility,
                    force: options.force || false,
                    files,
                    commitMessage: `Push from Vigthoria CLI: ${files.length} file(s)`
                })
            });
            if (!registerResponse.ok) {
                const error = await registerResponse.json().catch(async () => ({ error: await registerResponse.text() }));
                throw new Error(error.error || error.message || 'Failed to push project');
            }
            const registerData = await registerResponse.json();
            uploadSpinner.succeed(chalk.green('Project pushed successfully!'));
            console.log(chalk.cyan('\n📦 Project Details:'));
            console.log(chalk.gray(`   Name: ${registerData.project?.project_name || registerData.project?.name || answers.name}`));
            console.log(chalk.gray(`   Visibility: ${registerData.project?.visibility || answers.visibility}`));
            if (registerData.project?.id || registerData.projectId) {
                console.log(chalk.gray(`   ID: ${registerData.project?.id || registerData.projectId}`));
            }
            if ((registerData.project?.visibility || answers.visibility) === 'public') {
                console.log(chalk.cyan(`\n🔗 Public URL: ${registerData.url || `https://community.vigthoria.io/showcase/${registerData.project?.id || registerData.projectId}`}`));
            }
            console.log(chalk.gray('\nTip: Use `vigthoria repo pull <name>` to restore this project anywhere.\n'));
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Push failed');
            const errMsg = this.formatRepoError(error);
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * Pull a project from Vigthoria Repository
     */
    async pull(projectName, options = {}) {
        this.requireAuth();
        const spinner = createSpinner(`Fetching project: ${projectName}...`).start();
        try {
            const repo = await this.resolveRepoByName(projectName);
            const response = await this.repoFetch('/api/repo/pull', {
                method: 'POST',
                body: JSON.stringify({ projectId: repo.id })
            });
            if (!response.ok) {
                const error = await response.json().catch(async () => ({ error: await response.text() }));
                throw new Error(error.error || error.message || 'Project not found');
            }
            const data = await response.json();
            spinner.succeed(`Found project: ${chalk.cyan(data.project?.project_name || data.projectName || repo.name || repo.project_name || projectName)}`);
            const outputPath = options.output
                ? path.resolve(options.output)
                : path.join(process.cwd(), data.project?.project_name || data.projectName || repo.name || repo.project_name || projectName);
            if (fs.existsSync(outputPath) && !options.force) {
                const { overwrite } = await inquirer.prompt([{
                        type: 'confirm',
                        name: 'overwrite',
                        message: `Directory ${outputPath} exists. Overwrite?`,
                        default: false
                    }]);
                if (!overwrite) {
                    console.log(chalk.yellow(`\n${CH.warnEmoji}  Pull cancelled.\n`));
                    return;
                }
            }
            const downloadSpinner = createSpinner('Downloading project files...').start();
            // Create output directory
            fs.mkdirSync(outputPath, { recursive: true });
            // If we have a download URL, fetch and extract
            if (data.downloadUrl) {
                const archiveResponse = await fetch(data.downloadUrl, {
                    headers: this.getAuthHeaders()
                });
                if (!archiveResponse.ok) {
                    throw new Error('Failed to download project archive');
                }
                // Save and extract the archive
                const tempArchive = path.join(require('os').tmpdir(), `vigthoria-pull-${Date.now()}.zip`);
                const archiveBuffer = Buffer.from(await archiveResponse.arrayBuffer());
                fs.writeFileSync(tempArchive, archiveBuffer);
                // Extract archive - cross-platform
                const os = require('os');
                const platform = os.platform();
                if (platform === 'win32') {
                    // Use PowerShell's Expand-Archive — args as array to prevent injection
                    const { execFileSync } = await import('child_process');
                    execFileSync('powershell', [
                        '-NoProfile', '-NonInteractive', '-Command',
                        `Expand-Archive -Path '${tempArchive.replace(/'/g, "''")}' -DestinationPath '${outputPath.replace(/'/g, "''")}' -Force`
                    ], { stdio: 'ignore', windowsHide: true });
                }
                else {
                    // Use unzip on Unix-like systems — args as array to prevent injection
                    const { execFileSync } = await import('child_process');
                    execFileSync('unzip', ['-o', tempArchive, '-d', outputPath], { stdio: 'ignore' });
                }
                fs.unlinkSync(tempArchive);
            }
            else if (data.files) {
                // If we have files inline (small projects)
                for (const file of data.files) {
                    const filePath = path.join(outputPath, file.path);
                    fs.mkdirSync(path.dirname(filePath), { recursive: true });
                    fs.writeFileSync(filePath, file.content);
                }
            }
            downloadSpinner.succeed(chalk.green('Project pulled successfully!'));
            console.log(chalk.cyan('\n📁 Project extracted to:'));
            console.log(chalk.white(`   ${outputPath}`));
            console.log(chalk.gray(`\n   Tech Stack: ${data.project?.tech_stack || repo.tech_stack || 'Unknown'}`));
            console.log(chalk.gray(`   Description: ${data.project?.description || data.description || repo.description || '(none)'}`));
            console.log();
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Pull failed');
            const errMsg = this.formatRepoError(error);
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * List all projects in user's Vigthoria Repository
     */
    async list(options = {}) {
        this.requireAuth();
        const spinner = createSpinner('Fetching your projects...').start();
        try {
            const repos = await this.getMyRepos();
            const filteredRepos = options.visibility
                ? repos.filter((repo) => (repo.visibility || repo.is_public === true ? 'public' : 'private') === options.visibility)
                : repos;
            const data = {
                projects: filteredRepos,
                owned: filteredRepos,
                shared: [],
                total: filteredRepos.length
            };
            spinner.stop();
            if (data.projects.length === 0) {
                console.log(chalk.yellow('\n📦 No projects in your Vigthoria Repo yet.\n'));
                console.log(chalk.gray('Use `vigthoria repo push` to upload your first project.\n'));
                return;
            }
            // Separate owned and shared projects
            const ownedProjects = data.owned || data.projects.filter((p) => p.access_level === 'owner');
            const sharedProjects = data.shared || data.projects.filter((p) => p.access_level !== 'owner');
            console.log(chalk.cyan(`\n📦 Your Vigthoria Repository (${data.total} project${data.total !== 1 ? 's' : ''})\n`));
            // Display owned projects grouped by visibility
            if (ownedProjects.length > 0) {
                console.log(chalk.bold.cyan('  📁 YOUR PROJECTS'));
                console.log(chalk.gray('  ' + CH.hLine.repeat(50)));
                // Group by visibility
                const grouped = ownedProjects.reduce((acc, project) => {
                    const vis = project.visibility || 'private';
                    if (!acc[vis])
                        acc[vis] = [];
                    acc[vis].push(project);
                    return acc;
                }, {});
                const visibilityOrder = ['private', 'restricted', 'public'];
                const visibilityIcons = {
                    private: '🔒',
                    restricted: '👥',
                    public: '🌍'
                };
                visibilityOrder.forEach(vis => {
                    const projects = grouped[vis];
                    if (!projects || projects.length === 0)
                        return;
                    console.log(chalk.bold.white(`    ${visibilityIcons[vis]} ${vis.toUpperCase()}`));
                    projects.forEach((project) => {
                        const projectName = project.project_name || project.name || 'Unnamed';
                        const techStack = project.tech_stack || project.framework || 'Unknown';
                        const updatedAt = project.updated_at || project.updatedAt || project.created_at || project.createdAt;
                        const syncStatus = (project.last_synced_at || project.lastSyncedAt)
                            ? chalk.green(`${CH.success} synced`)
                            : chalk.yellow('- not synced');
                        console.log(chalk.white(`    ${projectName.padEnd(30)} ${syncStatus}`));
                        if (project.description) {
                            console.log(chalk.gray(`       ${project.description.substring(0, 50)}${project.description.length > 50 ? '...' : ''}`));
                        }
                        console.log(chalk.gray(`       Tech: ${techStack}`));
                        console.log(chalk.gray(`       Updated: ${updatedAt ? new Date(updatedAt).toLocaleDateString() : 'Unknown'}`));
                        console.log();
                    });
                });
            }
            // Display shared projects
            if (sharedProjects.length > 0) {
                console.log(chalk.bold.magenta('\n  🤝 SHARED WITH YOU'));
                console.log(chalk.gray('  ' + CH.hLine.repeat(50)));
                sharedProjects.forEach((project) => {
                    const projectName = project.project_name || project.name || 'Unnamed';
                    const techStack = project.tech_stack || project.framework || 'Unknown';
                    const updatedAt = project.updated_at || project.updatedAt || project.created_at || project.createdAt;
                    const accessIcon = project.access_level === 'admin' ? '👑' : project.access_level === 'write' ? '✏️' : '👁️';
                    console.log(chalk.white(`    ${accessIcon} ${projectName.padEnd(28)} [${project.access_level}]`));
                    if (project.description) {
                        console.log(chalk.gray(`       ${project.description.substring(0, 50)}${project.description.length > 50 ? '...' : ''}`));
                    }
                    console.log(chalk.gray(`       Tech: ${techStack}`));
                    console.log(chalk.gray(`       Updated: ${updatedAt ? new Date(updatedAt).toLocaleDateString() : 'Unknown'}`));
                    console.log();
                });
            }
            console.log(chalk.gray(CH.hLine.repeat(60)));
            console.log(chalk.cyan('\nCommands:'));
            console.log(chalk.gray('  vigthoria repo pull <name>     - Download a project'));
            console.log(chalk.gray('  vigthoria repo push            - Upload current directory'));
            console.log(chalk.gray('  vigthoria repo status          - Check sync status'));
            console.log(chalk.gray('  vigthoria repo share <name>    - Share a project\n'));
        }
        catch (error) {
            spinner.stop();
            this.logger.error('List failed');
            const errMsg = this.formatRepoError(error);
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * Show sync status of current project
     */
    async status() {
        this.requireAuth();
        const projectPath = process.cwd();
        const projectInfo = this.detectProjectInfo(projectPath);
        const spinner = createSpinner('Checking sync status...').start();
        try {
            const response = await fetch(`${this.apiBase}/api/repo/status/${encodeURIComponent(projectInfo.name)}`, {
                method: 'GET',
                headers: this.getAuthHeaders()
            });
            if (!response.ok) {
                spinner.succeed('Project not tracked in Vigthoria Repo');
                console.log(chalk.yellow('\n📦 Current project is not synced with Vigthoria Repo.\n'));
                console.log(chalk.gray('Use `vigthoria repo push` to upload it.\n'));
                return;
            }
            const data = await response.json();
            spinner.stop();
            const statusIcons = {
                synced: '✅',
                ahead: '⬆️',
                behind: '⬇️',
                diverged: CH.warnEmoji
            };
            console.log(chalk.cyan(`\n📦 Project: ${chalk.white(data.project.project_name)}\n`));
            console.log(chalk.gray(`  Path: ${projectPath}`));
            console.log(chalk.gray(`  Visibility: ${data.project.visibility}`));
            console.log(chalk.gray(`  Tech Stack: ${data.project.tech_stack || 'Unknown'}`));
            console.log();
            console.log(`  Status: ${statusIcons[data.syncStatus]} ${data.syncStatus.toUpperCase()}`);
            if (data.localChanges && data.localChanges > 0) {
                console.log(chalk.yellow(`  Local changes: ${data.localChanges} file(s) modified`));
            }
            console.log(chalk.gray(`\n  Last synced: ${data.project.last_synced_at
                ? new Date(data.project.last_synced_at).toLocaleString()
                : 'Never'}`));
            console.log();
            if (data.syncStatus === 'ahead' || data.syncStatus === 'diverged') {
                console.log(chalk.cyan('Tip: Use `vigthoria repo push` to sync changes.\n'));
            }
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Status check failed');
            const errMsg = error instanceof Error ? error.message : 'Unknown error';
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * Generate a shareable link for a project
     */
    async share(projectName, options = {}) {
        this.requireAuth();
        const spinner = createSpinner('Generating share link...').start();
        try {
            const response = await fetch(`${this.apiBase}/api/repo/share`, {
                method: 'POST',
                headers: this.getAuthHeaders(),
                body: JSON.stringify({
                    projectName,
                    expiresIn: options.expires || '7d'
                })
            });
            if (!response.ok) {
                const error = await response.json();
                throw new Error(error.error || 'Failed to generate share link');
            }
            const data = await response.json();
            spinner.succeed(chalk.green('Share link generated!'));
            console.log(chalk.cyan('\n🔗 Share Link:'));
            console.log(chalk.white(`   ${data.shareUrl}`));
            console.log(chalk.gray(`\n   Expires: ${new Date(data.expiresAt).toLocaleString()}`));
            console.log(chalk.gray('\n   Anyone with this link can view/download the project.\n'));
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Share failed');
            const errMsg = error instanceof Error ? error.message : 'Unknown error';
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * Delete a project from Vigthoria Repository
     */
    async delete(projectName) {
        this.requireAuth();
        const { confirm } = await inquirer.prompt([{
                type: 'confirm',
                name: 'confirm',
                message: chalk.red(`Are you sure you want to delete "${projectName}" from Vigthoria Repo?`),
                default: false
            }]);
        if (!confirm) {
            console.log(chalk.yellow(`\n${CH.warnEmoji}  Delete cancelled.\n`));
            return;
        }
        const spinner = createSpinner('Deleting project...').start();
        try {
            const response = await fetch(`${this.apiBase}/api/repo/projects/${encodeURIComponent(projectName)}`, {
                method: 'DELETE',
                headers: this.getAuthHeaders()
            });
            if (!response.ok) {
                const error = await response.json();
                throw new Error(error.error || 'Failed to delete project');
            }
            spinner.succeed(chalk.green('Project deleted from Vigthoria Repo'));
            console.log(chalk.gray('\nNote: Your local files are not affected.\n'));
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Delete failed');
            const errMsg = error instanceof Error ? error.message : 'Unknown error';
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
    /**
     * Open a project in a Vigthoria engine (shop, visual, game).
     * Pushes to community if not yet there, then triggers engine import.
     */
    async openIn(engine, projectName, options = {}) {
        this.requireAuth();
        const engineLabels = {
            shop: 'Shop Engine',
            visual: 'Visual Editor',
            game: 'Gaming Engine'
        };
        const label = engineLabels[engine] || engine;
        // Resolve project name from arg or current directory
        const resolvedName = projectName || this.detectProjectInfo(process.cwd()).name;
        const spinner = createSpinner(`Opening "${resolvedName}" in ${label}...`).start();
        try {
            const response = await fetch(`${this.apiBase}/api/engine-import`, {
                method: 'POST',
                headers: this.getAuthHeaders(),
                body: JSON.stringify({
                    engine,
                    projectName: resolvedName,
                    shopId: options.shopId || 'default',
                    source: 'repo'
                })
            });
            if (!response.ok) {
                const err = await response.json().catch(async () => ({ error: await response.text() }));
                throw new Error(err.error || `Engine import failed (${response.status})`);
            }
            const data = await response.json();
            spinner.succeed(chalk.green(`Project imported into ${label}!`));
            console.log(chalk.cyan(`\n🚀 Open in browser:`));
            console.log(chalk.bold(`   ${data.url}\n`));
            if (options.browser) {
                try {
                    const { execFileSync } = await import('child_process');
                    const platform = process.platform;
                    // Validate URL scheme before passing to OS — prevents shell injection
                    const parsedUrl = new URL(data.url);
                    if (parsedUrl.protocol !== 'https:' && parsedUrl.protocol !== 'http:') {
                        throw new Error('Unsafe URL scheme for browser open');
                    }
                    const safeUrl = parsedUrl.href;
                    if (platform === 'win32')
                        execFileSync('cmd', ['/c', 'start', '', safeUrl], { stdio: 'ignore', windowsHide: true });
                    else if (platform === 'darwin')
                        execFileSync('open', [safeUrl], { stdio: 'ignore' });
                    else
                        execFileSync('xdg-open', [safeUrl], { stdio: 'ignore' });
                }
                catch { /* browser open is optional */ }
            }
            if (data.message) {
                console.log(chalk.gray(`   ${data.message}\n`));
            }
        }
        catch (error) {
            spinner.stop();
            const errMsg = error instanceof Error ? error.message : 'Unknown error';
            console.log(chalk.red(`\n❌ ${label} import failed: ${errMsg}\n`));
            console.log(chalk.gray('Tip: Make sure your project is pushed first with `vigthoria repo push`\n'));
        }
    }
    /**
     * Clone a public project from Vigthoria Repository
     */
    async clone(projectUrl, options = {}) {
        // Parse project URL or name
        const projectIdMatch = projectUrl.match(/preview\/(\d+)/);
        const projectId = projectIdMatch ? projectIdMatch[1] : projectUrl;
        const spinner = createSpinner(`Cloning project...`).start();
        try {
            const response = await fetch(`${this.apiBase}/api/repo/clone/${projectId}`, {
                method: 'GET',
                headers: this.isAuthenticated() ? this.getAuthHeaders() : { 'Content-Type': 'application/json' }
            });
            if (!response.ok) {
                const error = await response.json();
                throw new Error(error.error || 'Project not found or not public');
            }
            const data = await response.json();
            spinner.succeed(`Found project: ${chalk.cyan(data.project.project_name)}`);
            // Use pull logic for the rest
            await this.pull(data.project.project_name, options);
        }
        catch (error) {
            spinner.stop();
            this.logger.error('Clone failed');
            const errMsg = error instanceof Error ? error.message : 'Unknown error';
            console.log(chalk.red(`\n❌ Error: ${errMsg}\n`));
        }
    }
}
