import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
import remarkGfm from 'remark-gfm';
import { cache } from 'react';

const contentDir = path.join(process.cwd(), 'content');

// Simple in-memory cache for development performance
const docCache = new Map<string, any>();
const sidebarCache: { data: any | null } = { data: null };

export interface DocMeta {
    title: string;
    slug: string[];
    description?: string;
    summary?: string;
}

export interface DocPage {
    meta: DocMeta;
    contentHtml: string;
}

export interface SidebarItem {
    title: string;
    slug: string;
    children?: SidebarItem[];
}

// Category display name mapping
const categoryNames: Record<string, string> = {
    gateway: '网关配置',
    channels: '渠道接入',
    install: '安装部署',
    cli: '命令行工具',
    concepts: '核心概念',
    tools: '工具系统',
    providers: '模型供应商',
    platforms: '平台适配',
    start: '快速入门',
    automation: '自动化',
    help: '帮助中心',
    nodes: '节点管理',
    plugins: '插件系统',
    web: 'Web 界面',
    security: '安全配置',
    reference: '参考手册',
    experiments: '实验功能',
    debug: '调试排查',
    diagnostics: '诊断工具',
    refactor: '重构指南',
    design: '设计文档',
    pipelines: '开发流水线',
};

export function getCategoryName(key: string): string {
    return categoryNames[key] || key;
}

function getAllMdFiles(dir: string, baseSlug: string[] = []): { filePath: string; slug: string[] }[] {
    const items: { filePath: string; slug: string[] }[] = [];
    if (!fs.existsSync(dir)) return items;

    const entries = fs.readdirSync(dir, { withFileTypes: true });
    for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);
        if (entry.isDirectory()) {
            items.push(...getAllMdFiles(fullPath, [...baseSlug, entry.name]));
        } else if (entry.name.endsWith('.md')) {
            const name = entry.name.replace(/\.md$/, '');
            items.push({ filePath: fullPath, slug: [...baseSlug, name] });
        }
    }
    return items;
}

export function getAllDocSlugs(): string[][] {
    return getAllMdFiles(contentDir).map(f => f.slug);
}

export const getDocBySlug = cache(async (slug: string[]): Promise<DocPage | null> => {
    const cacheKey = slug.join('/');
    if (docCache.has(cacheKey)) return docCache.get(cacheKey);

    // Try exact path first
    let filePath = path.join(contentDir, ...slug) + '.md';
    if (!fs.existsSync(filePath)) {
        // Try as directory with index.md
        filePath = path.join(contentDir, ...slug, 'index.md');
        if (!fs.existsSync(filePath)) {
            return null;
        }
    }

    const fileContent = fs.readFileSync(filePath, 'utf-8');
    const { data, content } = matter(fileContent);

    // Strip the first H1 heading from the markdown body since the page component
    // renders the title separately from meta.title. gray-matter may leave leading
    // newlines in content, so we trim the left first before matching.
    const contentWithoutH1 = content.replace(/^\s*#[^\n]*\n+/, '');

    // Process markdown
    const processedContent = await remark()
        .use(remarkGfm)
        .use(html, { sanitize: false })
        .process(contentWithoutH1);

    let contentHtml = processedContent.toString();

    // Fix internal links:
    // 1. Convert unparsed markdown links inside tags: [text](/link) -> <a href="/docs/link">text</a>
    // 2. Prefix absolute links with /docs (e.g. /gateway/config -> /docs/gateway/config)
    // 3. Strip .md from links (e.g. config.md -> config)
    contentHtml = contentHtml
        // Fix [text](/link) -> <a href="/docs/link">text</a> (happens inside custom tags like <Note>)
        .replace(/\[([^\]]+)\]\(\/([^)]+)\)/g, (match, text, link) => {
            const cleanLink = link.startsWith('docs/') ? link : `docs/${link.replace(/\.md$/, '')}`;
            return `<a href="/${cleanLink}">${text}</a>`;
        })
        // Fix href="/link" in standard tags or cards
        .replace(/href="\/([^/][^"]*)"/g, (match, p1) => {
            if (p1.startsWith('docs/')) return match;
            if (p1.startsWith('http')) return match;
            return `href="/docs/${p1.replace(/\.md$/, '')}"`;
        })
        // Fix any remaining .md in hrefs
        .replace(/href="([^"]+)\.md(#?[^"]*)"/g, 'href="$1$2"');

    // Clear cache to ensure changes are picked up immediately
    docCache.clear();
    sidebarCache.data = null;

    const result = {
        meta: {
            title: data.title || slug[slug.length - 1],
            slug,
            description: data.description,
            summary: data.summary,
        },
        contentHtml,
    };

    docCache.set(cacheKey, result);
    return result;
});

export const getSidebarStructure = cache((): SidebarItem[] => {
    if (sidebarCache.data) return sidebarCache.data;

    const items: SidebarItem[] = [];
    if (!fs.existsSync(contentDir)) return items;
    const entries = fs.readdirSync(contentDir, { withFileTypes: true });

    // Root-level .md files
    const rootFiles = entries.filter(e => !e.isDirectory() && e.name.endsWith('.md'));
    for (const f of rootFiles) {
        const name = f.name.replace(/\.md$/, '');
        const filePath = path.join(contentDir, f.name);
        const fileContent = fs.readFileSync(filePath, 'utf-8');
        const { data } = matter(fileContent);
        items.push({
            title: data.title || name,
            slug: `/docs/${name}`,
        });
    }

    // Directories
    const dirs = entries.filter(e => e.isDirectory()).sort((a, b) => {
        const order = ['start', 'install', 'gateway', 'channels', 'concepts', 'tools', 'providers', 'platforms', 'automation', 'cli', 'plugins', 'nodes', 'web', 'security', 'reference', 'help'];
        const ai = order.indexOf(a.name);
        const bi = order.indexOf(b.name);
        return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
    });

    for (const dir of dirs) {
        const dirPath = path.join(contentDir, dir.name);
        const children: SidebarItem[] = [];

        const subEntries = fs.readdirSync(dirPath, { withFileTypes: true });
        for (const sub of subEntries) {
            if (sub.isDirectory()) continue;
            if (!sub.name.endsWith('.md')) continue;
            const subName = sub.name.replace(/\.md$/, '');
            const subFilePath = path.join(dirPath, sub.name);
            const subContent = fs.readFileSync(subFilePath, 'utf-8');
            const { data } = matter(subContent);
            children.push({
                title: data.title || subName,
                slug: `/docs/${dir.name}/${subName}`,
            });
        }

        if (children.length > 0) {
            items.push({
                title: getCategoryName(dir.name),
                slug: `/docs/${dir.name}`,
                children,
            });
        }
    }

    sidebarCache.data = items;
    return items;
});
