import { NextRequest, NextResponse } from 'next/server'
import { getUserIdFromRequest } from '@/app/api/_helpers/session'
import {
    createGroupApply,
    deleteGroupApply,
    GroupApplyError,
    listGroupApplications,
    canReviewGroupApplications,
} from '@/server/groups/groupApply'
import { getDb } from '@/server/db'
import { resolveGroupIdFromParam } from '@/server/groups/groupIdUtils'

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

function applyErrorResponse(error: unknown) {
    if (error instanceof GroupApplyError) {
        if (error.code === 'ALREADY_MEMBER') {
            return NextResponse.json({ ok: false, message: error.message }, { status: 409 })
        }
        if (error.code === 'APPLICATION_CLOSED') {
            return NextResponse.json({ ok: false, message: error.message }, { status: 403 })
        }
    }
    return null
}

export async function GET(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const routeParam = String(params?.id ?? '').trim()
        const userId = await getUserIdFromRequest(request)
        if (!routeParam) {
            return NextResponse.json({ ok: false, message: 'Invalid group id' }, { status: 400 })
        }
        if (!userId) {
            return NextResponse.json({ ok: false, message: 'Unauthorized' }, { status: 401 })
        }

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

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

        const applications = await listGroupApplications(db, groupId)
        return NextResponse.json({ ok: true, applications })
    } catch (error: unknown) {
        console.error('Failed to list group applications:', error)
        return NextResponse.json(
            {
                ok: false,
                message: error instanceof Error ? error.message : 'Failed to list applications',
            },
            { status: 500 }
        )
    }
}

export async function POST(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const routeParam = String(params?.id ?? '').trim()
        const userId = await getUserIdFromRequest(request)
        if (!routeParam) {
            return NextResponse.json({ ok: false, message: 'Invalid group id' }, { status: 400 })
        }
        if (!userId) {
            return NextResponse.json({ ok: false, message: 'Unauthorized' }, { status: 401 })
        }

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

        const result = await createGroupApply(db, groupId, userId)
        return NextResponse.json({
            ok: true,
            applicationAt: result.applicationAt,
            created: result.created,
        })
    } catch (error: unknown) {
        const mapped = applyErrorResponse(error)
        if (mapped) return mapped
        console.error('Failed to create group application:', error)
        return NextResponse.json(
            {
                ok: false,
                message: error instanceof Error ? error.message : 'Failed to apply',
            },
            { status: 500 }
        )
    }
}

export async function DELETE(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const routeParam = String(params?.id ?? '').trim()
        const userId = await getUserIdFromRequest(request)
        if (!routeParam) {
            return NextResponse.json({ ok: false, message: 'Invalid group id' }, { status: 400 })
        }
        if (!userId) {
            return NextResponse.json({ ok: false, message: 'Unauthorized' }, { status: 401 })
        }

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

        const removed = await deleteGroupApply(db, groupId, userId, { logCancel: true })
        if (!removed) {
            return NextResponse.json({ ok: false, message: 'Application not found' }, { status: 404 })
        }
        return NextResponse.json({ ok: true })
    } catch (error: unknown) {
        console.error('Failed to cancel group application:', error)
        return NextResponse.json(
            {
                ok: false,
                message: error instanceof Error ? error.message : 'Failed to cancel application',
            },
            { status: 500 }
        )
    }
}
