/**
 * KB review-queue routes — settings-kb (wave-14).
 *
 * GET  /api/kb/review                      — list PENDING_REVIEW articles (admin/owner)
 * POST /api/kb/articles/:id/submit-review  — submit for review (kb:write author)
 * POST /api/kb/articles/:id/approve        — approve → PUBLISHED (users:manage)
 * POST /api/kb/articles/:id/reject         — reject → DRAFT (users:manage)
 */
import { Hono } from 'hono'
import { z } from 'zod'
import {
  createDb,
  kbTenantQuery,
  listPendingReview,
  submitForReview,
  approveArticle,
  rejectArticle,
  getKbSettings,
  KbArticleNotFoundError,
  KbArticleStatusError,
} from '@zync/db/queries'
import type { AppEnv } from '../types'
import { authMiddleware } from '../middleware/auth'
import { requirePermission } from '../middleware/guards'
import { requireModuleEnabled } from '../middleware/require-module-enabled'

const paginationSchema = z.object({
  page: z.coerce.number().int().min(1).optional().default(1),
  page_size: z.coerce.number().int().min(1).max(100).optional().default(20),
})

export const kbReviewRoute = new Hono<AppEnv>()

kbReviewRoute.use('*', authMiddleware)
kbReviewRoute.use('*', requireModuleEnabled('kb'))

// GET /api/kb/review
kbReviewRoute.get('/review', requirePermission('users:manage'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const parsed = paginationSchema.safeParse(c.req.query())
  if (!parsed.success) {
    return c.json({ error: 'Invalid query', details: parsed.error.flatten() }, 400)
  }

  const db = createDb(c.env)
  const result = await listPendingReview(db, session.tid, parsed.data.page, parsed.data.page_size)
  return c.json(result, 200)
})

// POST /api/kb/articles/:id/submit-review
kbReviewRoute.post('/articles/:id/submit-review', requirePermission('kb:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const articleId = c.req.param('id')
  const db = createDb(c.env)

  const kbSettings = await getKbSettings(db, session.tid)
  if (!kbSettings.kb_require_review) {
    return c.json(
      { error: 'Review workflow is not enabled for this workspace', code: 'REVIEW_DISABLED' },
      409,
    )
  }

  try {
    await submitForReview(db, session.tid, articleId)
    const article = await kbTenantQuery(db, session.tid).getArticleById(articleId)
    if (!article) return c.json({ error: 'Not found' }, 404)
    return c.json(article, 200)
  } catch (err) {
    if (err instanceof KbArticleNotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    if (err instanceof KbArticleStatusError) {
      return c.json({ error: err.message }, 409)
    }
    throw err
  }
})

// POST /api/kb/articles/:id/approve
kbReviewRoute.post('/articles/:id/approve', requirePermission('users:manage'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const db = createDb(c.env)
  try {
    await approveArticle(db, session.tid, c.req.param('id'), session.sub)
    return c.json({ ok: true }, 200)
  } catch (err) {
    if (err instanceof KbArticleNotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    if (err instanceof KbArticleStatusError) {
      return c.json({ error: err.message }, 409)
    }
    throw err
  }
})

const rejectArticleSchema = z.object({
  feedback: z.string().max(2000).optional(),
})

// POST /api/kb/articles/:id/reject
kbReviewRoute.post('/articles/:id/reject', requirePermission('users:manage'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const body = await c.req.json().catch(() => ({}))
  const parsed = rejectArticleSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 400)
  }

  const db = createDb(c.env)
  try {
    await rejectArticle(
      db,
      session.tid,
      c.req.param('id'),
      session.sub,
      parsed.data.feedback,
    )
    const feedback = parsed.data.feedback?.trim() || null
    return c.json({ ok: true, feedback }, 200)
  } catch (err) {
    if (err instanceof KbArticleNotFoundError) {
      return c.json({ error: 'Not found' }, 404)
    }
    if (err instanceof KbArticleStatusError) {
      return c.json({ error: err.message }, 409)
    }
    throw err
  }
})
