import { NextRequest, NextResponse } from 'next/server'
import crypto from 'crypto'
import { invitationRepo } from '@/lib/database/repositories/invitation.repo'
import { workspaceMemberRepo } from '@/lib/database/repositories/workspace-member.repo'
import { isAuthError, requireUser } from '@/lib/auth/session'
const INVITE_EXPIRY_DAYS = 7
/**
 * GET /api/invite
 * List all invitations for the current user (as inviter).
 * Returns separate lists: members (completed) + pending invites.
 */
export async function GET() {
  let currentUser
  try {
    currentUser = await requireUser()
  } catch (err) {
    if (isAuthError(err)) return err
    throw err
  }

  const rows = invitationRepo.listByInviter(currentUser.id)

  // Orphans are impossible: when a channel is deleted, the invitation row is
  // hard-deleted alongside it (see lib/invite/lifecycle.ts). We only return
  // rows that are still in the active pipeline.
  const toItem = (r: typeof rows[number]) => ({
    id: r.id,
    inviteToken: r.inviteToken,
    inviteePhone: r.inviteePhone,
    inviteeName: r.inviteeName,
    status: r.status,
    createdChannelId: r.createdChannelId,
    createdAt: r.createdAt,
    updatedAt: r.updatedAt,
  })
  const members = rows.filter((r) => r.status === 'completed').map(toItem)
  const pendingInvites = rows
    .filter((r) => r.status !== 'completed' && r.status !== 'expired' && r.status !== 'cancelled')
    .map(toItem)

  return NextResponse.json({ members, pendingInvites })
}

/**
 * POST /api/invite
 * Create a new invitation. Returns the invite link.
 *
 * Dedup: if the same inviter already has a 'pending' invitation created
 * within the last 5 seconds, return that one instead of creating a new row.
 * This guards against React 18 StrictMode double-firing the create effect.
 */
export async function POST() {
  let user
  try {
    user = await requireUser()
  } catch (err) {
    if (isAuthError(err)) return err
    throw err
  }

  // Determine project root from the host's most recently opened workspace
  const ws = workspaceMemberRepo.findProjectPathByOwner(user.id)
  const projectRoot = ws?.path || ''

  // Dedup: reuse a recent pending invitation from the same inviter
  const fiveSecondsAgo = Math.floor(Date.now() / 1000) - 5
  const recent = invitationRepo.findRecentPendingByInviter(user.id, fiveSecondsAgo)

  if (recent) {
    const origin = process.env.FORGE_PUBLIC_URL || process.env.BETTER_AUTH_URL || 'http://localhost:3000'
    return NextResponse.json(
      {
        id: recent.id,
        token: recent.inviteToken,
        link: `${origin}/invite/${recent.inviteToken}`,
        expiresAt: recent.expiresAt,
      },
      { status: 201 },
    )
  }

  // Generate unique invite token
  const token = `inv_${crypto.randomUUID().replace(/-/g, '').slice(0, 16)}`
  const id = crypto.randomUUID()
  const expiresAt = Math.floor(Date.now() / 1000) + INVITE_EXPIRY_DAYS * 86400

  invitationRepo.create({
    id,
    inviteToken: token,
    inviterUserId: user.id,
    projectRoot,
    expiresAt,
  })

  const origin = process.env.FORGE_PUBLIC_URL || process.env.BETTER_AUTH_URL || 'http://localhost:3000'
  const link = `${origin}/invite/${token}`

  return NextResponse.json({ id, token, link, expiresAt }, { status: 201 })
}
