/**
 * Staff contractor portal invite routes — contractor-portal (wave 8, Task 4).
 * Mounted under /api/contractors in contractors/router.ts.
 *
 *   POST /api/contractors/:id/portal-invite
 *   GET  /api/contractors/:id/portal-invite/status
 */
import { Hono } from 'hono'
import { generateOpaqueToken, hashToken } from '@zync/auth'
import { sendEmail } from '@zync/notifications'
import {
  ContractorNotFoundError,
  createPortalSession,
  getContractor,
  getPortalAccessStatus,
} from '@zync/db/queries'
import type { AppEnv } from '../types'
import { requirePermission } from '../middleware/guards'

const PORTAL_INVITE_TTL_MS = 24 * 60 * 60 * 1000

export const contractorPortalInviteRoutes = new Hono<AppEnv>()

contractorPortalInviteRoutes.post(
  '/:id/portal-invite',
  requirePermission('payouts:write'),
  async (c) => {
    const session = c.get('session')
    if (!session || session.type !== 'user' || !session.tid) {
      return c.json({ error: 'Unauthorized' }, 401)
    }

    const contractorId = c.req.param('id')
    const db = c.get('db')

    let contractor
    try {
      contractor = await getContractor(db, session.tid, contractorId)
    } catch (err) {
      if (err instanceof ContractorNotFoundError) return c.json({ error: 'Not found' }, 404)
      throw err
    }

    if (!contractor.active) {
      return c.json({ error: 'Contractor is inactive' }, 400)
    }

    if (!contractor.email) {
      return c.json({ error: 'Contractor has no email address' }, 400)
    }

    const plainToken = generateOpaqueToken()
    const tokenHash = await hashToken(plainToken)
    const expiresAt = new Date(Date.now() + PORTAL_INVITE_TTL_MS)

    await createPortalSession(db, {
      tenantId: session.tid,
      contractorId,
      tokenHash,
      expiresAt,
    })

    const link = `https://app.zync.is/contractor-portal/redeem?token=${encodeURIComponent(plainToken)}`
    const locale: 'he-IL' | 'en-US' = 'he-IL'

    await sendEmail(
      {
        to: contractor.email,
        templateKey: 'timer-magic-link',
        vars: {
          subject: 'גישה לפורטל הקבלנים',
          title: 'הזמנה לפורטל הקבלנים',
          body: `שלום ${contractor.name}, לחץ על הכפתור כדי לגשת לפורטל הזמן של Zync.`,
          link,
          ctaLabel: 'כניסה לפורטל',
          expiryNote: 'הקישור תקף ל-24 שעות.',
        },
        locale,
      },
      c.env,
    )

    return c.json({ sent: true, expiresAt: expiresAt.toISOString() }, 201)
  },
)

contractorPortalInviteRoutes.get(
  '/:id/portal-invite/status',
  requirePermission('payouts:read'),
  async (c) => {
    const session = c.get('session')
    if (!session || session.type !== 'user' || !session.tid) {
      return c.json({ error: 'Unauthorized' }, 401)
    }

    const contractorId = c.req.param('id')
    const db = c.get('db')

    try {
      await getContractor(db, session.tid, contractorId)
    } catch (err) {
      if (err instanceof ContractorNotFoundError) return c.json({ error: 'Not found' }, 404)
      throw err
    }

    const status = await getPortalAccessStatus(db, {
      tenantId: session.tid,
      contractorId,
    })

    return c.json(status)
  },
)
