import { readFile } from 'node:fs/promises'
import { join } from 'node:path'

export async function getDocMarkdown(slugPath: string): Promise<string> {
    const filePath = join(process.cwd(), 'content', 'docs', `${slugPath}.mdx`)
    const raw = await readFile(filePath, 'utf-8')
    return mdxToMarkdown(raw)
}

async function mdxToMarkdown(content: string): Promise<string> {
    let result = content

    // Remove frontmatter
    result = result.replace(/^---\n[\s\S]*?\n---\n*/, '')

    // Remove import lines
    result = result.replace(/^import\s+.*$/gm, '')

    // Replace <StandardSite /> with plain text
    result = result.replace(/<StandardSite\s*\/>/g, 'Standard.site')

    // Replace <LinkCard> components with markdown links, fetching OG titles
    const linkCardRegex = /<LinkCard\s+([\s\S]*?)\/>/g
    const linkCards: { match: string; url: string; title: string }[] = []

    for (const m of content.matchAll(linkCardRegex)) {
        const attrs = m[1]
        const url = attrs.match(/url=["']([^"']*)["']/)?.[1] ?? ''
        const title = attrs.match(/title=["']([^"']*)["']/)?.[1] ?? ''
        linkCards.push({ match: m[0], url, title })
    }

    // Fetch OG titles in parallel for cards without explicit titles
    const titles = await Promise.all(
        linkCards.map(async (card) => {
            if (card.title) return card.title
            return await fetchOgTitle(card.url)
        })
    )

    for (let i = 0; i < linkCards.length; i++) {
        result = result.replace(linkCards[i].match, `[${titles[i]}](${linkCards[i].url})`)
    }

    // Replace <Table> components with markdown tables
    // The closing /> is always on its own line, so we anchor to that to avoid
    // matching /> inside JSX fragments like </>
    result = result.replace(/<Table\s+([\s\S]*?)\n\/>/g, (_match, body) => {
        return parseTable(body)
    })

    // Clean up extra blank lines
    result = result.replace(/\n{3,}/g, '\n\n')

    return result.trim() + '\n'
}

async function fetchOgTitle(url: string): Promise<string> {
    try {
        const res = await fetch(url, {
            next: { revalidate: 86400 },
            headers: {
                'User-Agent': 'Mozilla/5.0 (compatible; Standard.site/1.0; +https://standard.site)'
            },
            signal: AbortSignal.timeout(5000),
        })

        if (!res.ok) return url

        const html = await res.text()
        const ogTitle =
            html.match(/<meta[^>]*property=["']og:title["'][^>]*content=["']([^"']*)["']/i)?.[1] ||
            html.match(/<meta[^>]*content=["']([^"']*)["'][^>]*property=["']og:title["']/i)?.[1] ||
            html.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1]

        return ogTitle?.trim() || url
    } catch {
        return url
    }
}

function parseTable(body: string): string {
    const headersMatch = body.match(/headers=\{(\[.*?\])}/)

    const rowsMatch = body.match(/rows=\{(\[[\s\S]*)\}\s*$/)

    if (!headersMatch || !rowsMatch) return body

    let headers: string[]
    try {
        // Convert single quotes to double quotes for JSON parsing
        headers = JSON.parse(headersMatch[1].replace(/'/g, '"'))
    } catch {
        return body
    }

    const rows = parseRows(rowsMatch[1])

    // Build markdown table
    const headerRow = '| ' + headers.join(' | ') + ' |'
    const separator = '| ' + headers.map(() => '---').join(' | ') + ' |'
    const dataRows = rows.map(row =>
        '| ' + row.map(cell => cell.replace(/\|/g, '\\|')).join(' | ') + ' |'
    )

    return [headerRow, separator, ...dataRows].join('\n')
}

function parseRows(raw: string): string[][] {
    const rows: string[][] = []

    // Strip outer brackets
    const inner = raw.trim().replace(/^\[/, '').replace(/\]$/, '')

    // Split into individual row arrays by matching balanced brackets
    const rowStrings = splitRows(inner)

    for (const rowStr of rowStrings) {
        const cells = splitCells(rowStr)
        if (cells.length > 0) {
            rows.push(cells.map(cell => jsxToPlainText(cell.trim())))
        }
    }

    return rows
}

function splitRows(content: string): string[] {
    const rows: string[] = []
    let depth = 0
    let current = ''
    let inString = false
    let stringChar = ''
    let inJsx = false

    for (let i = 0; i < content.length; i++) {
        const char = content[i]
        const prev = content[i - 1]

        if (inString) {
            current += char
            if (char === stringChar && prev !== '\\') {
                inString = false
            }
            continue
        }

        // Track JSX fragments: <> and </>
        if (char === '<' && content[i + 1] === '>') {
            inJsx = true
            current += char
            continue
        }
        if (char === '<' && content[i + 1] === '/' && content[i + 2] === '>') {
            inJsx = false
            current += char
            continue
        }

        // Only treat quotes as string delimiters outside JSX content
        if (!inJsx && (char === "'" || char === '"' || char === '`')) {
            inString = true
            stringChar = char
            current += char
            continue
        }

        if (char === '[') {
            if (depth > 0) current += char
            depth++
        } else if (char === ']') {
            depth--
            if (depth === 0) {
                rows.push(current.trim())
                current = ''
            } else {
                current += char
            }
        } else if (depth > 0) {
            current += char
        }
    }

    return rows
}

function splitCells(row: string): string[] {
    const cells: string[] = []
    let current = ''
    let depth = 0
    let inString = false
    let stringChar = ''
    let angleBracketDepth = 0
    let inJsx = false

    for (let i = 0; i < row.length; i++) {
        const char = row[i]
        const prev = row[i - 1]

        if (inString) {
            current += char
            if (char === stringChar && prev !== '\\') {
                inString = false
            }
            continue
        }

        // Track JSX fragments: <> and </>
        if (char === '<' && row[i + 1] === '>') {
            inJsx = true
            angleBracketDepth++
            current += char
            continue
        }
        if (char === '<' && row[i + 1] === '/' && row[i + 2] === '>') {
            inJsx = false
            current += char
            continue
        }

        // Only treat quotes as string delimiters outside JSX content
        if (!inJsx && (char === "'" || char === '"' || char === '`')) {
            inString = true
            stringChar = char
            current += char
            continue
        }

        if (char === '{') { depth++; current += char; continue }
        if (char === '}') { depth--; current += char; continue }
        if (char === '<') { angleBracketDepth++; current += char; continue }
        if (char === '>') { angleBracketDepth--; current += char; continue }

        if (char === ',' && depth === 0 && angleBracketDepth === 0) {
            cells.push(current.trim())
            current = ''
            continue
        }

        current += char
    }

    if (current.trim()) cells.push(current.trim())

    return cells
}

function jsxToPlainText(cell: string): string {
    // Remove wrapping quotes from plain strings
    if (/^['"].*['"]$/.test(cell)) {
        return cell.slice(1, -1)
    }

    // Handle JSX expressions wrapped in {<>...</>} or <>...</>
    let text = cell

    // Strip outer JSX expression wrapper: {<>...</>}
    text = text.replace(/^\{?<>/, '').replace(/<\/>\}?$/, '')

    // Convert <code>...</code> to backtick-wrapped text
    text = text.replace(/<code>([^<]*)<\/code>/g, '`$1`')

    // Convert <a href="...">...</a> to markdown links
    text = text.replace(/<a\s+href=["']([^"']*)["'][^>]*>([^<]*)<\/a>/g, '[$2]($1)')

    // Strip any remaining JSX tags
    text = text.replace(/<[^>]+>/g, '')

    // Clean up whitespace
    text = text.replace(/\s+/g, ' ').trim()

    return text
}