/**
 * Email sequences routes — email-marketing-sequences (wave-10 leaf 6).
 * Mounted at /api/marketing/sequences (via marketing router).
 *
 * GET    /                            list sequences
 * POST   /                            create sequence
 * GET    /:id                         get sequence detail + steps
 * PATCH  /:id                         update sequence
 * DELETE /:id                         delete sequence
 * GET    /:id/steps                   list steps
 * POST   /:id/steps                   add step
 * PATCH  /:id/steps/:stepId           update step
 * DELETE /:id/steps/:stepId           delete step
 * POST   /:id/enroll                  enroll contact in sequence
 * GET    /:id/enrollments             list enrollments for sequence
 */
import { Hono } from 'hono'
import { TenantTier } from '@zync/types/enums'
import type { AppEnv } from '../../types'
import { requirePermission, requireTier } from '../../middleware/guards'
import {
  listSequences,
  getSequence,
  createSequence,
  updateSequence,
  deleteSequence,
  listSequenceSteps,
  createSequenceStep,
  updateSequenceStep,
  deleteSequenceStep,
  listEnrollments,
  enrollInSequence,
  createSequenceSchema,
  updateSequenceSchema,
  createSequenceStepSchema,
  updateSequenceStepSchema,
  enrollInSequenceSchema,
  assertTenantOwnsLead,
  invalidTenantReferenceBody,
} from '@zync/db/queries'

export const sequencesRoute = new Hono<AppEnv>()

sequencesRoute.use('*', requireTier(TenantTier.BUSINESS))

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

  const sequences = await listSequences(db, session.tid)
  return c.json({ sequences })
})

// POST /api/marketing/sequences
sequencesRoute.post('/', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')

  const body = await c.req.json().catch(() => null)
  const parsed = createSequenceSchema.safeParse(body)
  if (!parsed.success) return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)

  const sequence = await createSequence(db, session.tid, session.sub, parsed.data)
  return c.json({ sequence }, 201)
})

// GET /api/marketing/sequences/:id
sequencesRoute.get('/:id', requirePermission('marketing:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const sequence = await getSequence(db, session.tid, id)
  if (!sequence) return c.json({ error: 'Sequence not found' }, 404)

  const steps = await listSequenceSteps(db, session.tid, id)
  return c.json({ sequence, steps })
})

// PATCH /api/marketing/sequences/:id
sequencesRoute.patch('/:id', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const body = await c.req.json().catch(() => null)
  const parsed = updateSequenceSchema.safeParse(body)
  if (!parsed.success) return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)

  try {
    const sequence = await updateSequence(db, session.tid, session.sub, id, parsed.data)
    return c.json({ sequence })
  } catch {
    return c.json({ error: 'Sequence not found' }, 404)
  }
})

// DELETE /api/marketing/sequences/:id
sequencesRoute.delete('/:id', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  await deleteSequence(db, session.tid, id)
  return c.json({ ok: true })
})

// GET /api/marketing/sequences/:id/steps
sequencesRoute.get('/:id/steps', requirePermission('marketing:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const steps = await listSequenceSteps(db, session.tid, id)
  return c.json({ steps })
})

// POST /api/marketing/sequences/:id/steps
sequencesRoute.post('/:id/steps', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const body = await c.req.json().catch(() => null)
  const parsed = createSequenceStepSchema.safeParse(body)
  if (!parsed.success) return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)

  const sequence = await getSequence(db, session.tid, id)
  if (!sequence) return c.json({ error: 'Sequence not found' }, 404)

  const step = await createSequenceStep(db, session.tid, id, parsed.data)
  return c.json({ step }, 201)
})

// PATCH /api/marketing/sequences/:id/steps/:stepId
sequencesRoute.patch('/:id/steps/:stepId', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { stepId } = c.req.param()

  const body = await c.req.json().catch(() => null)
  const parsed = updateSequenceStepSchema.safeParse(body)
  if (!parsed.success) return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)

  try {
    const step = await updateSequenceStep(db, session.tid, stepId, parsed.data)
    return c.json({ step })
  } catch {
    return c.json({ error: 'Step not found' }, 404)
  }
})

// DELETE /api/marketing/sequences/:id/steps/:stepId
sequencesRoute.delete('/:id/steps/:stepId', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { stepId } = c.req.param()

  await deleteSequenceStep(db, session.tid, stepId)
  return c.json({ ok: true })
})

// POST /api/marketing/sequences/:id/enroll
sequencesRoute.post('/:id/enroll', requirePermission('marketing:write'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const body = await c.req.json().catch(() => null)
  const parsed = enrollInSequenceSchema.safeParse(body)
  if (!parsed.success) return c.json({ error: 'Validation failed', issues: parsed.error.issues }, 400)

  const sequence = await getSequence(db, session.tid, id)
  if (!sequence) return c.json({ error: 'Sequence not found' }, 404)

  if (!(await assertTenantOwnsLead(db, session.tid, parsed.data.leadId ?? null))) {
    return c.json(invalidTenantReferenceBody('leadId'), 400)
  }

  const enrollment = await enrollInSequence(
    db,
    session.tid,
    session.sub,
    id,
    parsed.data.contactEmail,
    parsed.data.leadId,
  )
  return c.json({ enrollment }, 201)
})

// GET /api/marketing/sequences/:id/enrollments
sequencesRoute.get('/:id/enrollments', requirePermission('marketing:read'), async (c) => {
  const session = c.get('session')
  if (!session || session.type !== 'user' || !session.tid) return c.json({ error: 'Unauthorized' }, 401)
  const db = c.get('db')
  const { id } = c.req.param()

  const enrollments = await listEnrollments(db, session.tid, id)
  return c.json({ enrollments })
})
