import type { FastifyInstance } from 'fastify'
import { z } from 'zod'
import { db, logEvent } from '../db/index.js'

const bookmarkSchema = z.object({
  categoryId: z.number().int().nullable().optional(),
  title: z.string().min(1).max(128),
  url: z.string().url(),
  icon: z.string().optional(),
  favorite: z.boolean().optional(),
})

const categorySchema = z.object({
  name: z.string().min(1).max(64),
  icon: z.string().optional(),
  sortOrder: z.number().int().optional(),
})

export async function bookmarkRoutes(app: FastifyInstance) {
  app.addHook('onRequest', app.authenticate)

  app.get('/api/bookmarks/categories', async () => {
    const categories = db.prepare('SELECT * FROM bookmark_categories ORDER BY sort_order').all()
    return { categories }
  })

  app.post('/api/bookmarks/categories', async (req, reply) => {
    const parsed = categorySchema.safeParse(req.body)
    if (!parsed.success) return reply.code(400).send({ error: 'Invalid input' })
    const { name, icon, sortOrder } = parsed.data
    const result = db
      .prepare('INSERT INTO bookmark_categories (name, icon, sort_order) VALUES (?, ?, ?)')
      .run(name, icon ?? null, sortOrder ?? 0)
    return reply.code(201).send({ id: result.lastInsertRowid })
  })

  app.get('/api/bookmarks', async () => {
    const bookmarks = db.prepare('SELECT * FROM bookmarks ORDER BY created_at DESC').all()
    return { bookmarks }
  })

  app.post('/api/bookmarks', async (req, reply) => {
    const parsed = bookmarkSchema.safeParse(req.body)
    if (!parsed.success) return reply.code(400).send({ error: 'Invalid input' })
    const { categoryId, title, url, icon, favorite } = parsed.data
    const result = db
      .prepare(
        'INSERT INTO bookmarks (category_id, title, url, icon, favorite) VALUES (?, ?, ?, ?, ?)'
      )
      .run(categoryId ?? null, title, url, icon ?? null, favorite ? 1 : 0)
    logEvent('bookmark_created', `Bookmark added: ${title}`)
    return reply.code(201).send({ id: result.lastInsertRowid })
  })

  app.put('/api/bookmarks/:id', async (req, reply) => {
    const id = Number((req.params as { id: string }).id)
    const parsed = bookmarkSchema.partial().safeParse(req.body)
    if (!parsed.success) return reply.code(400).send({ error: 'Invalid input' })
    const existing = db.prepare('SELECT * FROM bookmarks WHERE id = ?').get(id) as
      | { category_id: number | null; title: string; url: string; icon: string | null; favorite: number }
      | undefined
    if (!existing) return reply.code(404).send({ error: 'Not found' })
    const categoryId = parsed.data.categoryId ?? existing.category_id
    const title = parsed.data.title ?? existing.title
    const url = parsed.data.url ?? existing.url
    const icon = parsed.data.icon ?? existing.icon
    const favorite = parsed.data.favorite ?? !!existing.favorite
    db.prepare(
      'UPDATE bookmarks SET category_id = ?, title = ?, url = ?, icon = ?, favorite = ? WHERE id = ?'
    ).run(categoryId, title, url, icon, favorite ? 1 : 0, id)
    return { ok: true }
  })

  app.delete('/api/bookmarks/:id', async (req, reply) => {
    const id = Number((req.params as { id: string }).id)
    const existing = db.prepare('SELECT title FROM bookmarks WHERE id = ?').get(id) as { title: string } | undefined
    db.prepare('DELETE FROM bookmarks WHERE id = ?').run(id)
    if (existing) logEvent('bookmark_deleted', `Bookmark removed: ${existing.title}`)
    return reply.code(204).send()
  })
}
