/**
 * Main orchestrator for Docusaurus setup
 * Coordinates all setup steps: install, config, sidebar, server launch
 */
import * as path from 'path';
import * as fs from '../../utils/fs-native.js';
import { checkNodeVersion, installDocusaurus, isDocusaurusInstalled } from './package-installer.js';
import { buildSidebar, countDocuments, countCategories } from './sidebar-builder.js';
import { writeDocusaurusConfig, writePackageJSON, writeCustomCSS, writeIndexPage, writeIndexModuleCSS, generateLogoSVG, generateFaviconSVG } from './config-generator.js';
import { startDevServer, findAvailablePort } from './server-manager.js';
import { detectProjectMetadata } from './project-detector.js';
import { SCOPE_PORTS, SCOPE_SITE_DIRS, SCOPE_DOC_DIRS } from './types.js';
/** Upper bound for port scanning when default port is busy */
const PORT_RANGE_END = 3030;
/** Primary theme color used for logo/favicon generation */
const PRIMARY_COLOR = '#4f46e5';
/**
 * Full Docusaurus setup workflow
 */
export async function setupDocusaurus(options) {
    const { projectRoot, targetDir, docsPath, config, force = false } = options;
    console.log('\u{1F4E6} Setting up documentation preview...\n');
    // Step 1: Check Node.js version
    console.log('1. Checking Node.js version...');
    const nodeVersion = await checkNodeVersion();
    if (!nodeVersion.compatible) {
        throw new Error(`Node.js 18+ required (found: ${nodeVersion.version})\n` +
            'Install Node.js from: https://nodejs.org/');
    }
    console.log(`   \u2705 Node.js ${nodeVersion.version}\n`);
    // Step 2: Check if packages already installed (skip npm install if so)
    const packagesInstalled = await isDocusaurusInstalled(targetDir);
    if (!force && packagesInstalled) {
        console.log('\u2705 Packages already installed\n');
    }
    else {
        // Step 3: Create target directory
        console.log('2. Creating docs-site directory...');
        await fs.ensureDir(targetDir);
        console.log('   \u2705 Directory created\n');
        // Step 4: Generate package.json
        console.log('3. Generating package.json...');
        await writePackageJSON(targetDir, config.title);
        console.log('   \u2705 package.json created\n');
        // Step 5: Install Docusaurus packages
        console.log('4. Installing packages (this may take 30-60 seconds)...');
        await installDocusaurus(targetDir);
        console.log('   \u2705 Installation complete\n');
    }
    // Always regenerate config files (picks up project metadata changes)
    console.log('5. Generating docusaurus.config.js...');
    await writeDocusaurusConfig(targetDir, config);
    console.log('   \u2705 Configuration generated\n');
    // Step 7: Count docs for info display
    console.log('6. Scanning documentation folders...');
    const sidebar = await buildSidebar({
        docsPath,
        excludeFolders: config.excludeFolders || ['legacy', 'node_modules', '_archive'],
        maxDepth: 5
    });
    const docCount = countDocuments(sidebar);
    const catCount = countCategories(sidebar);
    console.log(`   \u2705 Found ${docCount} documents in ${catCount} categories\n`);
    // Step 8: Write autogenerated sidebar
    console.log('7. Generating sidebars.js...');
    const sidebarPath = path.join(targetDir, 'sidebars.js');
    const autogeneratedSidebar = `/**
 * Auto-generated sidebar for documentation
 * Generated: ${new Date().toISOString()}
 * Uses Docusaurus autogenerated sidebar for reliability with large doc sets
 */

/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
  docs: [
    {
      type: 'autogenerated',
      dirName: '.',
    },
  ],
};

module.exports = sidebars;
`;
    await fs.writeFile(sidebarPath, autogeneratedSidebar, 'utf-8');
    console.log('   \u2705 Sidebar generated\n');
    // Step 9: Generate _category_.json and index pages for each doc category
    console.log('8. Generating category index pages...');
    const categories = config.projectMetadata?.categories || [];
    let categoryCount = 0;
    for (const cat of categories) {
        const catDir = path.join(docsPath, cat.id);
        if (await fs.pathExists(catDir)) {
            const categoryJson = JSON.stringify({
                label: cat.label,
                position: categories.indexOf(cat) + 1,
            }, null, 2);
            await fs.writeFile(path.join(catDir, '_category_.json'), categoryJson, 'utf-8');
            // Ensure category has an index page so /<name> route works
            // Without this, Docusaurus only creates /category/<name> for generated-index
            const hasIndex = await fs.pathExists(path.join(catDir, 'index.md'))
                || await fs.pathExists(path.join(catDir, 'README.md'));
            if (!hasIndex) {
                const indexContent = `---\ntitle: ${cat.label}\nsidebar_label: Overview\nslug: /${cat.id}\n---\n\n# ${cat.label}\n\n${cat.description || ''}\n`;
                await fs.writeFile(path.join(catDir, 'index.md'), indexContent, 'utf-8');
            }
            categoryCount++;
        }
    }
    console.log(`   \u2705 Generated ${categoryCount} category index pages\n`);
    // Step 10: Create landing page
    console.log('9. Creating landing page...');
    await writeIndexPage(targetDir, config.title, config.tagline, categories, config.projectMetadata?.name);
    await writeIndexModuleCSS(targetDir);
    console.log('   \u2705 Landing page created\n');
    // Step 11: Create custom CSS
    console.log('10. Creating custom theme...');
    await writeCustomCSS(targetDir, config.theme || 'default');
    console.log('   \u2705 Theme configured\n');
    // Step 12: Generate static assets (logo + favicon)
    console.log('11. Generating project assets...');
    const staticImgDir = path.join(targetDir, 'static', 'img');
    await fs.ensureDir(staticImgDir);
    const metadata = config.projectMetadata;
    if (metadata) {
        // Use custom logo if available, otherwise generate from initials
        if (metadata.logoPath && await fs.pathExists(metadata.logoPath)) {
            await fs.copyFile(metadata.logoPath, path.join(staticImgDir, 'logo.svg'));
        }
        else {
            const logoSvg = generateLogoSVG(metadata.initials, PRIMARY_COLOR);
            await fs.writeFile(path.join(staticImgDir, 'logo.svg'), logoSvg, 'utf-8');
        }
        const faviconSvg = generateFaviconSVG(metadata.initials, PRIMARY_COLOR);
        await fs.writeFile(path.join(staticImgDir, 'favicon.svg'), faviconSvg, 'utf-8');
    }
    console.log('   \u2705 Assets generated\n');
    // Step 13: Copy increment specs for link resolution in Docusaurus
    console.log('12. Copying increment specs for link resolution...');
    const incrementsSource = path.join(projectRoot, '.specweave', 'increments');
    const incrementsStaticDest = path.join(targetDir, 'static', 'increments');
    if (await fs.pathExists(incrementsSource)) {
        let copiedCount = 0;
        const incrementDirs = await fs.readdir(incrementsSource, { withFileTypes: true });
        for (const dir of incrementDirs) {
            if (!dir.isDirectory() || dir.name.startsWith('_'))
                continue;
            const specFile = path.join(incrementsSource, dir.name, 'spec.md');
            if (await fs.pathExists(specFile)) {
                const destDir = path.join(incrementsStaticDest, dir.name);
                await fs.ensureDir(destDir);
                await fs.copyFile(specFile, path.join(destDir, 'spec.md'));
                copiedCount++;
            }
        }
        console.log(`   \u2705 Copied ${copiedCount} increment spec(s)\n`);
    }
    else {
        console.log('   \u2705 No increments to copy\n');
    }
    console.log('\u2705 Setup complete!\n');
}
/**
 * Quick setup with defaults — detects project metadata automatically
 */
export async function quickSetup(projectRoot, scope = 'internal') {
    const targetDir = path.join(projectRoot, '.specweave', SCOPE_SITE_DIRS[scope]);
    const docsPath = path.join(projectRoot, '.specweave', 'docs', SCOPE_DOC_DIRS[scope]);
    // Check if docs exist
    if (!await fs.pathExists(docsPath)) {
        throw new Error(scope === 'public'
            ? 'No public documentation found.\n' +
                'Create public docs in .specweave/docs/public/'
            : 'No documentation found.\n' +
                'Create documentation by completing your first increment:\n' +
                '  sw:increment "your feature"');
    }
    // Detect project metadata
    const metadata = await detectProjectMetadata(projectRoot, docsPath);
    const titleSuffix = scope === 'internal' ? ' (Internal)' : '';
    const config = {
        title: `${metadata.name} Documentation${titleSuffix}`,
        tagline: metadata.description,
        url: 'http://localhost',
        baseUrl: '/',
        docsPath: `../docs/${SCOPE_DOC_DIRS[scope]}`,
        port: SCOPE_PORTS[scope],
        theme: 'default',
        excludeFolders: ['legacy', 'node_modules', '_archive'],
        projectMetadata: metadata,
        scope
    };
    await setupDocusaurus({
        projectRoot,
        targetDir,
        docsPath,
        config
    });
}
/**
 * Launch preview (setup if needed, then start server)
 */
export async function launchPreview(projectRoot, options = {}) {
    const scope = options.scope || 'internal';
    const targetDir = path.join(projectRoot, '.specweave', SCOPE_SITE_DIRS[scope]);
    const docsPath = path.join(projectRoot, '.specweave', 'docs', SCOPE_DOC_DIRS[scope]);
    const defaultPort = SCOPE_PORTS[scope];
    // Check if docs exist
    if (!await fs.pathExists(docsPath)) {
        throw new Error(scope === 'public'
            ? 'No public documentation found.\n' +
                'Create public docs in .specweave/docs/public/'
            : 'No documentation found.\n' +
                'Create documentation by completing your first increment:\n' +
                '  sw:increment "your feature"');
    }
    // Detect project metadata and run setup once (force flag passed through)
    const metadata = await detectProjectMetadata(projectRoot, docsPath);
    const titleSuffix = scope === 'internal' ? ' (Internal)' : '';
    const config = {
        title: `${metadata.name} Documentation${titleSuffix}`,
        tagline: metadata.description,
        url: 'http://localhost',
        baseUrl: '/',
        docsPath: `../docs/${SCOPE_DOC_DIRS[scope]}`,
        port: defaultPort,
        theme: 'default',
        excludeFolders: ['legacy', 'node_modules', '_archive'],
        projectMetadata: metadata,
        scope
    };
    await setupDocusaurus({
        projectRoot,
        targetDir,
        docsPath,
        config,
        force: options.force
    });
    // Find available port
    const port = options.port || await findAvailablePort(defaultPort, PORT_RANGE_END);
    console.log(`Starting server on port ${port}...`);
    // Start dev server
    const server = await startDevServer(targetDir, {
        port,
        openBrowser: options.openBrowser !== false
    });
    console.log(`\n\u{1F310} Documentation available at: ${server.url}`);
    console.log('\u{1F504} Hot reload enabled - edit docs and see changes instantly');
    console.log('\u{1F4A1} Press Ctrl+C to stop the server\n');
    return server;
}
/**
 * Build static site
 */
export async function buildStaticSite(projectRoot, scope = 'internal') {
    const targetDir = path.join(projectRoot, '.specweave', SCOPE_SITE_DIRS[scope]);
    // Check if installed
    if (!await isDocusaurusInstalled(targetDir)) {
        throw new Error('Docusaurus not installed.\n' +
            'Run: sw:docs preview (this will install it)');
    }
    console.log('\u{1F4E6} Building static documentation site...\n');
    const { spawn } = await import('child_process');
    return new Promise((resolve, reject) => {
        const buildProcess = spawn('npm', ['run', 'build'], {
            cwd: targetDir,
            stdio: 'inherit',
            shell: true
        });
        buildProcess.on('close', (code) => {
            if (code === 0) {
                const buildPath = path.join(targetDir, 'build');
                console.log('\n\u2705 Build complete!');
                console.log(`\u{1F4C1} Output: ${buildPath}\n`);
                resolve();
            }
            else {
                reject(new Error(`Build failed with code ${code}`));
            }
        });
        buildProcess.on('error', (error) => {
            reject(new Error(`Failed to start build: ${error.message}`));
        });
    });
}
/**
 * Check if setup is needed
 */
export async function isSetupNeeded(projectRoot, scope = 'internal') {
    const targetDir = path.join(projectRoot, '.specweave', SCOPE_SITE_DIRS[scope]);
    return !(await isDocusaurusInstalled(targetDir));
}
/**
 * Get docs site path
 */
export function getDocsSitePath(projectRoot, scope = 'internal') {
    return path.join(projectRoot, '.specweave', SCOPE_SITE_DIRS[scope]);
}
/**
 * Get docs path
 */
export function getDocsPath(projectRoot, scope = 'internal') {
    return path.join(projectRoot, '.specweave', 'docs', SCOPE_DOC_DIRS[scope]);
}
//# sourceMappingURL=docusaurus-setup.js.map