import { Hono } from "hono"
import { Database } from "bun:sqlite"
import { join } from "path"

export const DATA_DIR = process.env.DATA_DIR || "."
const api = new Hono()
const db = new Database(join(DATA_DIR, "bbs.sqlite"))

api.use("*", async (c, next) => {
    const method = c.req.method
    const url = c.req.url

    let body = ""
    if (method === "POST" || method === "PUT" || method === "PATCH") {
        try {
            const clonedRequest = c.req.raw.clone()
            body = await clonedRequest.text()
            console.log(`${method} ${url} - Body: ${body}`)
        } catch (error) {
            console.log(`${method} ${url} - Body: [unable to parse]`)
        }
    } else {
        console.log(`${method} ${url}`)
    }

    await next()
})

db.run(`
    CREATE TABLE IF NOT EXISTS topics (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title TEXT NOT NULL,
        content TEXT NOT NULL,
        author TEXT NOT NULL,
        created_at TEXT NOT NULL
    );

    CREATE TABLE IF NOT EXISTS replies (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        topic_id INTEGER NOT NULL,
        content TEXT NOT NULL,
        author TEXT NOT NULL,
        created_at TEXT NOT NULL
    );
`)

api.get("/topics", async c => {
    const topics = db.query("SELECT * FROM topics ORDER BY id DESC").all()
    return c.json(topics)
})

api.post("/topics", async c => {
    const { title, content, author } = await c.req.json()

    if (!title || !content || !author) {
        return c.json({ error: "title, content and author are required" }, 400)
    }

    const topic = db.query(`
        INSERT INTO
        topics(title, content, author, created_at)
        VALUES($title, $content, $author, $created_at)
    `).run({ $title: title, $content: content, $author: author, $created_at: new Date().toISOString() })
    return c.json({ id: topic.lastInsertRowid, ok: true })
})

api.get("/topics/:id", async c => {
    const id = c.req.param("id")
    if (!id) {
        return c.json({ error: "id is required" }, 400)
    }

    let topic = db.query("SELECT * FROM topics WHERE id = $id").get({ $id: id })
    if (!topic) {
        return c.json({ error: "topic not found" }, 404)
    }
    const replies = db.query("SELECT * FROM replies WHERE topic_id = $id").all({ $id: id })
        ; (topic as any).replies = replies

    return c.json(topic)
})

api.post("/topics/:id/reply", async c => {
    const id = c.req.param("id")
    if (!id) {
        return c.json({ error: "id is required" }, 400)
    }
    const { content, author } = await c.req.json()
    const reply = db.query(`
        INSERT INTO replies (topic_id, content, author, created_at)
        VALUES ($topic_id, $content, $author, $created_at)
    `).run({ $topic_id: id, $content: content, $author: author, $created_at: new Date().toISOString() })
    return c.json({ id: reply.lastInsertRowid, ok: true })
})

export default {
    port: process.env.PORT || 3001,
    fetch: api.fetch,
}