/**
 * Task status CRUD + reorder routes — tasks-board-engine.
 *
 * Mounted at /api/tasks (behind authMiddleware + requireModuleEnabled('tasks')).
 *
 * GET    /statuses              list statuses (query: project?)
 * POST   /statuses              create status
 * PATCH  /statuses/reorder      reorder statuses
 * PATCH  /statuses/:id          update status
 * DELETE /statuses/:id          delete status (body: { reassignToStatusId })
 *
 * All require tasks:write except GET which requires tasks:read.
 */
import { Hono } from 'hono'
import type { AppEnv } from '../types'
import { requirePermission } from '../middleware/guards'
import {
  listStatuses,
  createStatus,
  updateStatus,
  deleteStatus,
  reorderStatuses,
  assertTenantOwnsProject,
  invalidTenantReferenceBody,
} from '@zync/db/queries'
import {
  createStatusSchema,
  updateStatusSchema,
  deleteStatusSchema,
  reorderStatusSchema,
  statusListQuerySchema,
} from '../schemas/tasks'

export const taskStatusesRoute = new Hono<AppEnv>()

// GET /api/tasks/statuses
taskStatusesRoute.get('/statuses', requirePermission('tasks:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  const url = new URL(c.req.url)
  const rawQuery = Object.fromEntries(url.searchParams.entries())
  const parsed = statusListQuerySchema.safeParse(rawQuery)
  if (!parsed.success) {
    return c.json({ error: 'Invalid query', issues: parsed.error.issues }, 422)
  }

  const db = c.get('db')
  const statuses = await listStatuses(db, session.tid, parsed.data.project)
  return c.json(statuses, 200)
})

// POST /api/tasks/statuses
taskStatusesRoute.post('/statuses', requirePermission('tasks:write'), 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(() => null)
  const parsed = createStatusSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 422)
  }

  const db = c.get('db')

  if (!(await assertTenantOwnsProject(db, session.tid, parsed.data.project_id))) {
    return c.json(invalidTenantReferenceBody('project_id'), 400)
  }

  const status = await createStatus(db, session.tid, {
    name: parsed.data.name,
    color: parsed.data.color,
    projectId: parsed.data.project_id ?? null,
    isTerminal: parsed.data.is_terminal,
  })
  return c.json(status, 201)
})

// PATCH /api/tasks/statuses/reorder — must be BEFORE /:id to avoid shadowing
taskStatusesRoute.patch('/statuses/reorder', requirePermission('tasks:write'), 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(() => null)
  const parsed = reorderStatusSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 422)
  }

  const db = c.get('db')
  await reorderStatuses(db, session.tid, parsed.data.order)
  return c.json({ ok: true }, 200)
})

// PATCH /api/tasks/statuses/:id
taskStatusesRoute.patch('/statuses/:id', requirePermission('tasks:write'), 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(() => null)
  const parsed = updateStatusSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 422)
  }

  const db = c.get('db')
  const status = await updateStatus(db, session.tid, c.req.param('id'), {
    name: parsed.data.name,
    color: parsed.data.color,
    isTerminal: parsed.data.is_terminal,
  })
  return c.json(status, 200)
})

// DELETE /api/tasks/statuses/:id
taskStatusesRoute.delete('/statuses/:id', requirePermission('tasks:write'), 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(() => null)
  const parsed = deleteStatusSchema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Invalid request', issues: parsed.error.issues }, 422)
  }

  const db = c.get('db')
  await deleteStatus(db, session.tid, c.req.param('id'), parsed.data.reassignToStatusId)
  return c.body(null, 204)
})
