import { NextRequest, NextResponse } from 'next/server'
import { getUserIdFromRequest } from '@/app/api/_helpers/session'
import {
    approveGroupApply,
    canReviewGroupApplications,
    GroupApplyError,
    rejectGroupApply,
} from '@/server/groups/groupApply'
import { notifyGroupApplyApproved } from '@/server/groups/notifyGroupApplyAction'
import { getDb } from '@/server/db'
import { resolveGroupIdFromParam } from '@/server/groups/groupIdUtils'

export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'

const VALID_ACTIONS = new Set(['approve', 'reject'])

export async function PATCH(
    request: NextRequest,
    { params }: { params: { id: string; userId: string } }
) {
    try {
        const routeParam = String(params?.id ?? '').trim()
        const applicantUserId = String(params?.userId ?? '').trim()
        const actorId = await getUserIdFromRequest(request)

        if (!routeParam || !applicantUserId) {
            return NextResponse.json({ ok: false, message: 'Invalid parameters' }, { status: 400 })
        }
        if (!actorId) {
            return NextResponse.json({ ok: false, message: 'Unauthorized' }, { status: 401 })
        }

        const body = (await request.json().catch(() => ({}))) as { action?: string }
        const action = String(body?.action ?? '').trim()
        if (!VALID_ACTIONS.has(action)) {
            return NextResponse.json({ ok: false, message: 'Invalid action' }, { status: 400 })
        }

        const db = await getDb()
        const groupId = await resolveGroupIdFromParam(db, routeParam)
        if (!groupId) {
            return NextResponse.json({ ok: false, message: 'Group not found' }, { status: 404 })
        }

        const actorMembership = await db.get<{ role: string }>(
            `SELECT role FROM user_groups WHERE group_id = ? AND user_id = ?`,
            [groupId, actorId]
        )
        if (!actorMembership || !canReviewGroupApplications(actorMembership.role)) {
            return NextResponse.json({ ok: false, message: 'Forbidden' }, { status: 403 })
        }

        if (action === 'approve') {
            await approveGroupApply(db, groupId, applicantUserId, actorId)
            void notifyGroupApplyApproved(db, {
                groupId,
                applicantUserId,
                actorUserId: actorId,
            })
            return NextResponse.json({ ok: true, action: 'approve' })
        }

        const removed = await rejectGroupApply(db, groupId, applicantUserId, actorId)
        if (!removed) {
            return NextResponse.json({ ok: false, message: 'Application not found' }, { status: 404 })
        }
        return NextResponse.json({ ok: true, action: 'reject' })
    } catch (error: unknown) {
        if (error instanceof GroupApplyError) {
            if (error.code === 'NOT_FOUND') {
                return NextResponse.json({ ok: false, message: error.message }, { status: 404 })
            }
            if (error.code === 'ALREADY_MEMBER') {
                return NextResponse.json({ ok: false, message: error.message }, { status: 409 })
            }
        }
        console.error('Failed to review group application:', error)
        return NextResponse.json(
            {
                ok: false,
                message: error instanceof Error ? error.message : 'Failed to review application',
            },
            { status: 500 }
        )
    }
}
