/**
 * Data export & GDPR routes — data-export-gdpr (wave-10 leaf 8).
 *
 * Mounted at /api/data in the main route index.
 *
 * Routes:
 *   POST /data/export                    — create export job, return jobId
 *   GET  /data/export/:jobId             — poll status
 *   GET  /data/export/:jobId/download    — return JSON file
 *   POST /customers/:id/anonymize        — GDPR erasure (requires OWNER role)
 *
 * Note: anonymize route mounted separately via customerRoutes for OWNER guard.
 */
import { Hono } from 'hono'
import { z } from 'zod'
import type { AppEnv } from '../../types'
import { authMiddleware } from '../../middleware/auth'
import { requirePermission } from '../../middleware/guards'
import {
  createExportJob,
  getExportJobStatus,
  exportTenantData,
  anonymizeCustomer,
  setExportJobProcessing,
  completeExportJob,
  failExportJob,
} from '@zync/db/queries'
import { isOwnerOrAdminRole } from '../../lib/system-roles'

const dataExportRoutes = new Hono<AppEnv>()

dataExportRoutes.use('*', authMiddleware)

// ── POST /data/export ──────────────────────────────────────────────────────────

dataExportRoutes.post('/export', requirePermission('settings:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'No tenant context' }, 403)
  }
  const tenantId = session.tid
  const userId = session.sub
  const db = c.get('db')

  const jobId = await createExportJob(db, tenantId, userId)

  // Kick off async export inline (Cloudflare Workers: no detached promises)
  // We mark it processing immediately and complete synchronously.
  // In production this would be queued; here we do it eagerly.
  try {
    await setExportJobProcessing(db, tenantId, jobId)
    // Validate that export data can be collected (throws on error)
    await exportTenantData(db, tenantId)
    // downloadUrl points to the download endpoint (real impl would write to R2)
    const downloadUrl = `/api/data/export/${jobId}/download`
    await completeExportJob(db, tenantId, jobId, downloadUrl)
  } catch (err) {
    const msg = err instanceof Error ? err.message : 'Unknown error'
    await failExportJob(db, tenantId, jobId, msg)
  }

  return c.json({ jobId }, 202)
})

// ── GET /data/export/:jobId ────────────────────────────────────────────────────

dataExportRoutes.get('/export/:jobId', requirePermission('settings:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'No tenant context' }, 403)
  }
  const tenantId = session.tid
  const jobId = c.req.param('jobId')
  const db = c.get('db')

  const job = await getExportJobStatus(db, tenantId, jobId)
  if (!job) return c.json({ error: 'Export job not found' }, 404)

  return c.json(job)
})

// ── GET /data/export/:jobId/download ──────────────────────────────────────────

dataExportRoutes.get(
  '/export/:jobId/download',
  requirePermission('settings:read'),
  async (c) => {
    const session = c.get('session')
    if (!session || session.type !== 'user' || !session.tid) {
      return c.json({ error: 'No tenant context' }, 403)
    }
    const tenantId = session.tid
    const jobId = c.req.param('jobId')
    const db = c.get('db')

    const job = await getExportJobStatus(db, tenantId, jobId)
    if (!job) return c.json({ error: 'Export job not found' }, 404)
    if (job.status !== 'completed') {
      return c.json({ error: 'Export not ready', status: job.status }, 409)
    }

    // S8-i2-008: only the job creator or OWNER/ADMIN may download the export.
    const isCreator = job.createdBy !== null && job.createdBy === session.sub
    const isPrivileged = isOwnerOrAdminRole(session.role)
    if (!isCreator && !isPrivileged) {
      return c.json({ error: 'Forbidden' }, 403)
    }

    // Re-generate export data for download
    const data = await exportTenantData(db, tenantId)
    const json = JSON.stringify(data, null, 2)

    return new Response(json, {
      headers: {
        'Content-Type': 'application/json',
        'Content-Disposition': `attachment; filename="zync-export-${tenantId.slice(0, 8)}-${new Date().toISOString().slice(0, 10)}.json"`,
      },
    })
  },
)

// ── POST /customers/:id/anonymize ──────────────────────────────────────────────
// Mounted separately — requires OWNER role check.

const anonymizeRoutes = new Hono<AppEnv>()
anonymizeRoutes.use('*', authMiddleware)

anonymizeRoutes.post('/:id/anonymize', requirePermission('customers:delete'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) {
    return c.json({ error: 'No tenant context' }, 403)
  }

  // OWNER-only gate: role must be OWNER
  const role = session.role as string | undefined
  if (role !== 'OWNER') {
    return c.json({ error: 'Only workspace OWNER may anonymize customers' }, 403)
  }

  const tenantId = session.tid
  const userId = session.sub
  const customerId = c.req.param('id')
  const db = c.get('db')

  const schema = z.object({ confirm: z.literal(true) })
  const body = await c.req.json().catch(() => ({}))
  const parsed = schema.safeParse(body)
  if (!parsed.success) {
    return c.json({ error: 'Send { confirm: true } to confirm GDPR erasure' }, 400)
  }

  try {
    await anonymizeCustomer(db, tenantId, userId, customerId)
    return c.json({ ok: true, customerId })
  } catch (err) {
    if (err instanceof Error && err.message === 'Customer not found or access denied') {
      return c.json({ error: err.message }, 404)
    }
    throw err
  }
})

export { dataExportRoutes, anonymizeRoutes }
