import 'server-only'

import fs from 'node:fs'
import path from 'node:path'
import { marked } from 'marked'

/**
 * File-based blog: drop a Markdown file into content/blog/<slug>.md and it is
 * published at /blog/<slug>. Posts are read at build time (static generation),
 * so serving them costs nothing at runtime.
 *
 * Frontmatter (between --- lines at the top of the file):
 *   title:   Post title            (required)
 *   date:    YYYY-MM-DD            (required, used for ordering)
 *   excerpt: One-two sentences shown on the index and in search results
 *   author:  Display name          (optional)
 */

export interface BlogPostMeta {
  slug: string
  title: string
  date: string
  excerpt: string
  author: string | null
}

export interface BlogPost extends BlogPostMeta {
  html: string
}

const BLOG_DIR = path.join(process.cwd(), 'content', 'blog')

function parseFrontmatter(raw: string): { meta: Record<string, string>; body: string } {
  const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/)
  if (!match) return { meta: {}, body: raw }
  const meta: Record<string, string> = {}
  for (const line of match[1].split(/\r?\n/)) {
    const idx = line.indexOf(':')
    if (idx === -1) continue
    meta[line.slice(0, idx).trim()] = line.slice(idx + 1).trim()
  }
  return { meta, body: match[2] }
}

function readPost(fileName: string): BlogPost | null {
  const slug = fileName.replace(/\.md$/, '')
  const raw = fs.readFileSync(path.join(BLOG_DIR, fileName), 'utf8')
  const { meta, body } = parseFrontmatter(raw)
  if (!meta.title || !meta.date) return null
  return {
    slug,
    title: meta.title,
    date: meta.date,
    excerpt: meta.excerpt ?? '',
    author: meta.author ?? null,
    html: marked.parse(body, { async: false }),
  }
}

export function getAllPosts(): BlogPost[] {
  if (!fs.existsSync(BLOG_DIR)) return []
  return fs
    .readdirSync(BLOG_DIR)
    .filter((f) => f.endsWith('.md'))
    .map(readPost)
    .filter((p): p is BlogPost => p !== null)
    .sort((a, b) => b.date.localeCompare(a.date))
}

export function getPost(slug: string): BlogPost | null {
  // Slug comes from the URL — never let it traverse out of the blog directory.
  if (!/^[a-z0-9-]+$/.test(slug)) return null
  const file = path.join(BLOG_DIR, `${slug}.md`)
  if (!fs.existsSync(file)) return null
  return readPost(`${slug}.md`)
}
