import { NextResponse } from 'next/server';
import { readFileSync, existsSync, readdirSync } from 'fs';
import { join, basename, isAbsolute } from 'path';
import matter from 'gray-matter';
import { CacheUtils } from '@/lib/cache';
import { importOpenAPISpec } from '@/lib/api-docs/parsers/openapi';
import { generateAPISummary, formatAPISummaryForPrompt } from '@/lib/api-docs/agent/spec-summary';
import { getProjectContent } from '@/lib/storage/blob';
import { isDevMode, shouldShowItem } from '@/lib/docs/config/environment';
// Configuration
const STARTER_PATH = process.env.STARTER_PATH || 'devdoc-docs';
const LOCAL_SPEC_PATH = process.env.LOCAL_SPEC_PATH || `${STARTER_PATH}/api-reference/openapi.json`;
// Helper to resolve paths - supports both relative and absolute STARTER_PATH
function resolvePath(...paths) {
    if (isAbsolute(STARTER_PATH)) {
        return join(STARTER_PATH, ...paths);
    }
    return join(process.cwd(), STARTER_PATH, ...paths);
}
// Get the content root directory
function getContentRoot() {
    if (isAbsolute(STARTER_PATH)) {
        return STARTER_PATH;
    }
    return join(process.cwd(), STARTER_PATH);
}
// Debug logging - only in verbose mode
if (process.env.DEVDOC_VERBOSE === 'true') {
    console.log('[Collections] Config:', {
        starterPath: STARTER_PATH,
        localSpecPath: LOCAL_SPEC_PATH
    });
}
// Cache configuration
const CACHE_KEY = 'collections-local';
const CACHE_TTL = 60 * 5 // 5 minutes
;
const FALLBACK_CACHE_KEY = `${CACHE_KEY}-fallback`;
const SUMMARY_CACHE_KEY = 'api-summary-local';
const SUMMARY_CACHE_TTL = 60 * 60 * 24 // 1 day
;
// Load GraphQL schema from local file
function loadGraphQLSchema(schemaPath) {
    try {
        // Resolve the path similar to OpenAPI spec
        const relativePath = schemaPath;
        const fullPath = relativePath.startsWith(STARTER_PATH) || isAbsolute(relativePath) ? isAbsolute(relativePath) ? relativePath : resolvePath(relativePath.replace(STARTER_PATH + '/', '')) : resolvePath(relativePath);
        if (!existsSync(fullPath)) {
            return null;
        }
        const content = readFileSync(fullPath, 'utf-8');
        return content;
    } catch (error) {
        console.error('[Collections] Error loading GraphQL schema:', error);
        return null;
    }
}
// Load OpenAPI spec from local file
function loadLocalSpec(specPath) {
    try {
        // Use provided path or default
        const relativePath = specPath || LOCAL_SPEC_PATH;
        // If the path already includes STARTER_PATH prefix, use it; otherwise prepend
        const fullPath = relativePath.startsWith(STARTER_PATH) || isAbsolute(relativePath) ? isAbsolute(relativePath) ? relativePath : resolvePath(relativePath.replace(STARTER_PATH + '/', '')) : resolvePath(relativePath);
        if (!existsSync(fullPath)) {
            return null;
        }
        const content = readFileSync(fullPath, 'utf-8');
        const spec = JSON.parse(content);
        return spec;
    } catch (error) {
        console.error('[Collections] Error loading local spec:', error);
        return null;
    }
}
// Load docs.json configuration
function loadDocsConfig() {
    try {
        const configPath = resolvePath('docs.json');
        if (!existsSync(configPath)) {
            return null;
        }
        const content = readFileSync(configPath, 'utf-8');
        return JSON.parse(content);
    } catch (error) {
        console.error('[Collections] Error loading docs.json:', error);
        return null;
    }
}
// Load theme.json configuration
function loadThemeConfig() {
    try {
        const configPath = resolvePath('theme.json');
        if (!existsSync(configPath)) {
            return null;
        }
        const content = readFileSync(configPath, 'utf-8');
        return JSON.parse(content);
    } catch (error) {
        console.error('[Collections] Error loading theme.json:', error);
        return null;
    }
}
// Load custom CSS content
function loadCustomCss(cssPath) {
    if (!cssPath) return null;
    try {
        const fullPath = resolvePath(cssPath);
        if (!existsSync(fullPath)) {
            return null;
        }
        return readFileSync(fullPath, 'utf-8');
    } catch (error) {
        console.error('[Collections] Error loading custom CSS:', error);
        return null;
    }
}
// Load MDX page metadata
function loadPageMeta(pagePath) {
    try {
        const contentRoot = getContentRoot();
        // Try .mdx then .md
        let fullPath = join(contentRoot, `${pagePath}.mdx`);
        if (!existsSync(fullPath)) {
            fullPath = join(contentRoot, `${pagePath}.md`);
        }
        if (!existsSync(fullPath)) {
            return null;
        }
        const content = readFileSync(fullPath, 'utf-8');
        const { data } = matter(content);
        return {
            title: data.title || basename(pagePath),
            description: data.description,
            icon: data.icon
        };
    } catch (error) {
        console.error('[Collections] Error loading page meta:', pagePath, error);
        return null;
    }
}
// Extract navigation tabs from docs.json in order
// Filters out private tabs when in production mode
function buildNavigationTabs(config, devMode) {
    const tabs = [];
    const isDev = devMode ?? isDevMode();
    if (!config.navigation?.tabs) {
        return tabs;
    }
    config.navigation.tabs.forEach((tab, index)=>{
        // Skip private tabs in production mode
        if (!shouldShowItem(tab.visibility, isDev)) {
            return;
        }
        // Convert tab name to id (e.g., "API Reference" -> "api-reference")
        const id = tab.tab.toLowerCase().replace(/\s+/g, '-');
        // Determine the type (default to 'docs' if not specified)
        const type = tab.type || 'docs';
        // Build versions array for openapi tabs
        let versions;
        if (tab.type === 'openapi' && tab.versions && tab.versions.length > 0) {
            versions = tab.versions.map((v)=>({
                    version: v.version,
                    spec: v.spec,
                    default: v.default || false
                }));
            // Ensure at least one default
            if (!versions.some((v)=>v.default)) {
                versions[0].default = true;
            }
        }
        // Build graphql schemas array for graphql tabs
        let graphqlSchemas;
        if (tab.type === 'graphql') {
            if (tab.schemas && tab.schemas.length > 0) {
                // Multiple schemas
                graphqlSchemas = tab.schemas.map((s)=>({
                        name: s.name || 'GraphQL API',
                        schema: s.schema,
                        endpoint: s.endpoint,
                        default: s.default || false
                    }));
                // Ensure at least one default
                if (!graphqlSchemas.some((s)=>s.default)) {
                    graphqlSchemas[0].default = true;
                }
            } else if (tab.schema && tab.endpoint) {
                // Single schema
                graphqlSchemas = [
                    {
                        name: tab.tab,
                        schema: tab.schema,
                        endpoint: tab.endpoint,
                        default: true
                    }
                ];
            }
        }
        tabs.push({
            id,
            tab: tab.tab,
            type,
            path: tab.path,
            order: index,
            versions,
            graphqlSchemas,
            visibility: tab.visibility
        });
    });
    return tabs;
}
// Build documentation groups from docs.json
// Filters out private tabs and groups when in production mode
function buildDocGroups(config, devMode) {
    const groups = [];
    const isDev = devMode ?? isDevMode();
    if (!config.navigation?.tabs) {
        return groups;
    }
    // Helper to process a page item (string or nested group)
    const processPageItem = (pageItem, index, parentGroup)=>{
        // Handle nested group
        if (typeof pageItem === 'object' && 'group' in pageItem) {
            const nestedGroup = pageItem;
            const children = [];
            for(let j = 0; j < nestedGroup.pages.length; j++){
                const childPath = nestedGroup.pages[j];
                if (typeof childPath === 'string') {
                    const childMeta = loadPageMeta(childPath);
                    if (childMeta) {
                        children.push({
                            id: `doc-${childPath.replace(/\//g, '-')}`,
                            slug: childPath,
                            title: childMeta.title,
                            description: childMeta.description,
                            icon: childMeta.icon,
                            filePath: childPath,
                            group: nestedGroup.group,
                            order: j
                        });
                    }
                }
            }
            if (children.length > 0) {
                // Return a group item with children
                return {
                    id: `group-${nestedGroup.group}`.toLowerCase().replace(/\s+/g, '-'),
                    slug: '',
                    title: nestedGroup.group,
                    filePath: '',
                    group: parentGroup,
                    order: index,
                    isGroup: true,
                    children
                };
            }
            return null;
        }
        // Handle string page path
        const pagePath = pageItem;
        const meta = loadPageMeta(pagePath);
        if (meta) {
            return {
                id: `doc-${pagePath.replace(/\//g, '-')}`,
                slug: pagePath,
                title: meta.title,
                description: meta.description,
                icon: meta.icon,
                filePath: pagePath,
                group: parentGroup,
                order: index
            };
        }
        return null;
    };
    // Iterate through all tabs and their groups
    for (const tab of config.navigation.tabs){
        // Skip private tabs in production mode
        if (!shouldShowItem(tab.visibility, isDev)) {
            continue;
        }
        // Skip tabs without groups (like API Reference with just href)
        if (!tab.groups) {
            continue;
        }
        for (const group of tab.groups){
            // Skip private groups in production mode
            if (!shouldShowItem(group.visibility, isDev)) {
                continue;
            }
            const pages = [];
            for(let i = 0; i < group.pages.length; i++){
                const pageItem = group.pages[i];
                const page = processPageItem(pageItem, i, group.group);
                if (page) {
                    pages.push(page);
                }
            }
            if (pages.length > 0) {
                groups.push({
                    id: `group-${tab.tab}-${group.group}`.toLowerCase().replace(/\s+/g, '-'),
                    title: group.group,
                    pages,
                    order: groups.length,
                    icon: group.icon
                });
            }
        }
    }
    return groups;
}
// Scan changelog directory for release files
function scanChangelogReleases() {
    const releases = [];
    const changelogDir = resolvePath('changelog');
    if (!existsSync(changelogDir)) {
        return releases;
    }
    try {
        const files = readdirSync(changelogDir);
        for (const file of files){
            // Only process versioned files (v1.0.0.mdx, etc.), skip latest.mdx and index files
            if (!file.match(/^v[\d.]+\.mdx?$/)) {
                continue;
            }
            const filePath = join(changelogDir, file);
            const content = readFileSync(filePath, 'utf-8');
            const { data } = matter(content);
            const version = data.version || file.replace(/\.mdx?$/, '');
            releases.push({
                version,
                date: data.date || '',
                title: data.title || version,
                slug: `changelog/${file.replace(/\.mdx?$/, '')}`
            });
        }
        // Sort by version (newest first)
        releases.sort((a, b)=>{
            const versionA = a.version.replace(/^v/, '').split('.').map(Number);
            const versionB = b.version.replace(/^v/, '').split('.').map(Number);
            for(let i = 0; i < Math.max(versionA.length, versionB.length); i++){
                const numA = versionA[i] || 0;
                const numB = versionB[i] || 0;
                if (numA !== numB) return numB - numA;
            }
            return 0;
        });
    } catch (error) {
        console.error('[Collections] Error scanning changelog:', error);
    }
    return releases;
}
// Get OpenAPI spec from local file
function getOpenApiSpec(specPath) {
    return loadLocalSpec(specPath);
}
/**
 * Handle multi-tenant request - fetch content from Blob Storage
 */ async function handleMultiTenantRequest(projectSlug, request) {
    try {
        const projectContent = await getProjectContent(projectSlug);
        if (!projectContent) {
            return NextResponse.json({
                error: 'Project not found'
            }, {
                status: 404
            });
        }
        // Parse docs.json from project content
        const docsConfig = JSON.parse(projectContent.docsJson);
        // Build navigation tabs and doc groups from config
        // Multi-tenant projects are always in production mode (deployed), so devMode=false
        const navigationTabs = buildNavigationTabs(docsConfig, false);
        const docGroups = buildDocGroupsFromBlob(docsConfig, projectContent);
        // For now, return docs-only response (no OpenAPI spec from blob)
        return NextResponse.json({
            id: projectSlug,
            name: docsConfig.name || 'Documentation',
            description: 'Documentation',
            folders: [],
            requests: [],
            auth: {
                authType: 'none',
                authActive: true
            },
            headers: [],
            variables: [],
            apiSummary: null,
            docGroups,
            navigationTabs,
            changelogReleases: [],
            docsName: docsConfig.name || null,
            docsFavicon: docsConfig.favicon || null,
            docsLogo: null,
            docsHeader: null,
            docsNavbar: null,
            docsColors: null,
            defaultTheme: null,
            customCss: null,
            apiVersions: [],
            selectedApiVersion: null,
            notice: docsConfig.notice || null,
            isMultiTenant: true,
            projectSlug
        }, {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'public, max-age=60'
            }
        });
    } catch (error) {
        console.error('[Collections] Multi-tenant error:', error);
        return NextResponse.json({
            error: 'Failed to load project'
        }, {
            status: 500
        });
    }
}
/**
 * Build doc groups from Blob storage content
 * Note: Multi-tenant (deployed) projects are always in production mode,
 * so private tabs and groups are always filtered out
 */ function buildDocGroupsFromBlob(config, content) {
    const groups = [];
    // Multi-tenant projects are always in production mode (deployed)
    const isDev = false;
    if (!config.navigation?.tabs) {
        return groups;
    }
    // Helper to find file content
    const findFileContent = (pagePath)=>{
        const mdxPath = `${pagePath}.mdx`;
        const mdPath = `${pagePath}.md`;
        const file = content.files.find((f)=>f.path === mdxPath || f.path === mdPath);
        if (!file) return null;
        try {
            const { data } = matter(file.content);
            return {
                title: data.title || basename(pagePath),
                description: data.description,
                icon: data.icon
            };
        } catch  {
            return {
                title: basename(pagePath)
            };
        }
    };
    // Process tabs and groups
    for (const tab of config.navigation.tabs){
        // Skip private tabs (multi-tenant is always production)
        if (!shouldShowItem(tab.visibility, isDev)) {
            continue;
        }
        if (!tab.groups) continue;
        for (const group of tab.groups){
            // Skip private groups (multi-tenant is always production)
            if (!shouldShowItem(group.visibility, isDev)) {
                continue;
            }
            const pages = [];
            for(let i = 0; i < group.pages.length; i++){
                const pageItem = group.pages[i];
                if (typeof pageItem === 'string') {
                    const meta = findFileContent(pageItem);
                    if (meta) {
                        pages.push({
                            id: `doc-${pageItem.replace(/\//g, '-')}`,
                            slug: pageItem,
                            title: meta.title,
                            description: meta.description,
                            icon: meta.icon,
                            filePath: pageItem,
                            group: group.group,
                            order: i
                        });
                    }
                } else if ('group' in pageItem) {
                    // Nested group
                    const children = [];
                    for(let j = 0; j < pageItem.pages.length; j++){
                        const childPath = pageItem.pages[j];
                        if (typeof childPath === 'string') {
                            const childMeta = findFileContent(childPath);
                            if (childMeta) {
                                children.push({
                                    id: `doc-${childPath.replace(/\//g, '-')}`,
                                    slug: childPath,
                                    title: childMeta.title,
                                    description: childMeta.description,
                                    icon: childMeta.icon,
                                    filePath: childPath,
                                    group: pageItem.group,
                                    order: j
                                });
                            }
                        }
                    }
                    if (children.length > 0) {
                        pages.push({
                            id: `group-${pageItem.group}`.toLowerCase().replace(/\s+/g, '-'),
                            slug: '',
                            title: pageItem.group,
                            filePath: '',
                            group: group.group,
                            order: i,
                            isGroup: true,
                            children
                        });
                    }
                }
            }
            if (pages.length > 0) {
                groups.push({
                    id: `group-${tab.tab}-${group.group}`.toLowerCase().replace(/\s+/g, '-'),
                    title: group.group,
                    pages,
                    order: groups.length,
                    icon: group.icon
                });
            }
        }
    }
    return groups;
}
// Helper to generate or get cached summary
async function getOrGenerateSummary(collection, specVersion) {
    const versionedCacheKey = `${SUMMARY_CACHE_KEY}-v${specVersion}`;
    const cachedSummary = await CacheUtils.get(versionedCacheKey);
    if (cachedSummary) {
        return cachedSummary;
    }
    const summary = generateAPISummary(collection);
    const formattedSummary = formatAPISummaryForPrompt(summary);
    await CacheUtils.set(versionedCacheKey, formattedSummary, SUMMARY_CACHE_TTL);
    return formattedSummary;
}
export async function GET(request) {
    try {
        // Check for multi-tenant mode (project slug from middleware)
        const projectSlug = request.headers.get('x-devdoc-project');
        // If multi-tenant, fetch from Blob Storage
        if (projectSlug && !projectSlug.startsWith('custom:')) {
            return handleMultiTenantRequest(projectSlug, request);
        }
        // Parse query params
        const { searchParams } = new URL(request.url);
        const requestedVersion = searchParams.get('version');
        // Load docs and theme configuration
        const docsConfig = loadDocsConfig();
        const themeConfig = loadThemeConfig();
        const customCss = loadCustomCss(themeConfig?.customCss);
        const docGroups = docsConfig ? buildDocGroups(docsConfig) : [];
        const navigationTabs = docsConfig ? buildNavigationTabs(docsConfig) : [];
        const changelogReleases = scanChangelogReleases();
        // Find the OpenAPI tab and its versions
        const openapiTab = navigationTabs.find((t)=>t.type === 'openapi');
        const apiVersions = openapiTab?.versions || [];
        // Determine which spec to load
        let specPath;
        let selectedVersion;
        if (apiVersions.length > 0) {
            // Find requested version or default
            const versionConfig = requestedVersion ? apiVersions.find((v)=>v.version === requestedVersion) : apiVersions.find((v)=>v.default) || apiVersions[0];
            if (versionConfig) {
                specPath = versionConfig.spec;
                selectedVersion = versionConfig.version;
            }
        }
        // Get OpenAPI spec (with optional path for versioned specs)
        const spec = await getOpenApiSpec(specPath);
        // Handle no spec available
        if (!spec) {
            return NextResponse.json({
                id: 'empty',
                name: docsConfig?.name || 'Documentation',
                description: 'Welcome to the documentation.',
                folders: [],
                requests: [],
                auth: {
                    authType: 'none',
                    authActive: true
                },
                headers: [],
                variables: [],
                apiSummary: null,
                docGroups,
                navigationTabs,
                changelogReleases,
                docsName: docsConfig?.name || null,
                docsFavicon: docsConfig?.favicon || null,
                docsLogo: themeConfig?.logo || null,
                docsHeader: themeConfig?.header || null,
                docsNavbar: themeConfig?.navbar || null,
                docsColors: themeConfig?.colors || null,
                defaultTheme: themeConfig?.defaultTheme || null,
                customCss: customCss || null,
                apiVersions,
                selectedApiVersion: selectedVersion,
                notice: docsConfig?.notice || null
            }, {
                headers: {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-cache, no-store, must-revalidate'
                }
            });
        }
        // Check if spec has paths
        if (!spec.paths || Object.keys(spec.paths).length === 0) {
            return NextResponse.json({
                id: 'empty',
                name: spec.info?.title || docsConfig?.name || 'Documentation',
                description: spec.info?.description || 'No endpoints defined.',
                folders: [],
                requests: [],
                auth: {
                    authType: 'none',
                    authActive: true
                },
                headers: [],
                variables: [],
                apiSummary: null,
                docGroups,
                navigationTabs,
                changelogReleases,
                docsName: docsConfig?.name || null,
                docsFavicon: docsConfig?.favicon || null,
                docsLogo: themeConfig?.logo || null,
                docsHeader: themeConfig?.header || null,
                docsNavbar: themeConfig?.navbar || null,
                docsColors: themeConfig?.colors || null,
                defaultTheme: themeConfig?.defaultTheme || null,
                customCss: customCss || null,
                apiVersions,
                selectedApiVersion: selectedVersion,
                notice: docsConfig?.notice || null
            }, {
                headers: {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-cache, no-store, must-revalidate'
                }
            });
        }
        // Convert to BrainfishCollection using our parser
        const collections = await importOpenAPISpec(spec);
        const collection = collections[0];
        if (!collection) {
            return NextResponse.json(null, {
                headers: {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-cache, no-store, must-revalidate'
                }
            });
        }
        // Generate or get cached API summary
        const specVersion = spec.info?.version || 'unknown';
        const apiSummary = await getOrGenerateSummary(collection, specVersion);
        // Return collection with summary and doc groups
        return NextResponse.json({
            ...collection,
            apiSummary,
            specVersion,
            docGroups,
            navigationTabs,
            changelogReleases,
            docsName: docsConfig?.name || null,
            docsFavicon: docsConfig?.favicon || null,
            docsLogo: themeConfig?.logo || null,
            docsHeader: themeConfig?.header || null,
            docsNavbar: themeConfig?.navbar || null,
            docsColors: themeConfig?.colors || null,
            defaultTheme: themeConfig?.defaultTheme || null,
            customCss: customCss || null,
            apiVersions,
            selectedApiVersion: selectedVersion,
            notice: docsConfig?.notice || null
        }, {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-cache, no-store, must-revalidate'
            }
        });
    } catch (error) {
        console.error('[Collections] Unexpected error:', error);
        return NextResponse.json({
            id: 'error',
            name: 'Documentation',
            description: 'Failed to load documentation.',
            folders: [],
            requests: [],
            auth: {
                authType: 'none',
                authActive: true
            },
            headers: [],
            variables: [],
            docGroups: []
        }, {
            headers: {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-cache, no-store, must-revalidate'
            }
        });
    }
}
