import { NextRequest, NextResponse } from 'next/server'
import { getUserIdFromRequest } from '@/app/api/_helpers/session'
import {
    GROUP_ROLE_DEPUTY,
    GROUP_ROLE_LEADER,
    GROUP_ROLE_MEMBER,
    type GroupMemberAction,
    isGroupDeputyRole,
    isGroupLeaderRole,
} from '@/lib/groups/groupMemberRole'
import { GROUP_LOG_ACTION } from '@/lib/groups/groupLogActions'
import { getDb } from '@/server/db'
import { logGroupAction } from '@/server/groups/insertGroupLog'
import { resolveGroupIdFromParam } from '@/server/groups/groupIdUtils'
import { notifyGroupMemberAction } from '@/server/groups/notifyGroupMemberAction'

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

const VALID_ACTIONS = new Set<GroupMemberAction>([
    'transfer_leader',
    'demote_member',
    'promote_deputy',
    'kick',
])

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

        if (!routeParam || !targetUserId) {
            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() as GroupMemberAction
        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 || !isGroupLeaderRole(actorMembership.role)) {
            return NextResponse.json({ ok: false, message: 'Forbidden' }, { status: 403 })
        }

        const targetMembership = await db.get<{ role: string }>(
            `SELECT role FROM user_groups WHERE group_id = ? AND user_id = ?`,
            [groupId, targetUserId]
        )
        if (!targetMembership) {
            return NextResponse.json({ ok: false, message: 'Member not found' }, { status: 404 })
        }

        if (action === 'kick') {
            if (targetUserId === actorId) {
                return NextResponse.json({ ok: false, message: 'Cannot kick yourself' }, { status: 400 })
            }
            await db.run(`DELETE FROM user_groups WHERE group_id = ? AND user_id = ?`, [
                groupId,
                targetUserId,
            ])
            void notifyGroupMemberAction(db, {
                groupId,
                action: 'kick',
                targetUserId,
                actorUserId: actorId,
            }).catch((err) => console.error('[group] notify kick failed:', err))
            logGroupAction(db, {
                groupId,
                userId: actorId,
                targetId: targetUserId,
                actionContent: GROUP_LOG_ACTION.MEMBER_KICKED,
            })
            return NextResponse.json({ ok: true, action })
        }

        if (action === 'transfer_leader') {
            if (targetUserId === actorId) {
                return NextResponse.json({ ok: false, message: 'Invalid target' }, { status: 400 })
            }
            await db.run(`UPDATE user_groups SET role = ? WHERE group_id = ? AND user_id = ?`, [
                GROUP_ROLE_MEMBER,
                groupId,
                actorId,
            ])
            await db.run(`UPDATE user_groups SET role = ? WHERE group_id = ? AND user_id = ?`, [
                GROUP_ROLE_LEADER,
                groupId,
                targetUserId,
            ])
            void notifyGroupMemberAction(db, {
                groupId,
                action: 'transfer_leader',
                targetUserId,
                actorUserId: actorId,
            }).catch((err) => console.error('[group] notify transfer_leader failed:', err))
            logGroupAction(db, {
                groupId,
                userId: actorId,
                targetId: targetUserId,
                actionContent: GROUP_LOG_ACTION.LEADER_TRANSFERRED,
            })
            return NextResponse.json({ ok: true, action })
        }

        if (action === 'demote_member') {
            if (isGroupLeaderRole(targetMembership.role)) {
                return NextResponse.json(
                    { ok: false, message: 'Cannot demote family head directly' },
                    { status: 400 }
                )
            }
            await db.run(`UPDATE user_groups SET role = ? WHERE group_id = ? AND user_id = ?`, [
                GROUP_ROLE_MEMBER,
                groupId,
                targetUserId,
            ])
            void notifyGroupMemberAction(db, {
                groupId,
                action: 'demote_member',
                targetUserId,
                actorUserId: actorId,
            }).catch((err) => console.error('[group] notify demote_member failed:', err))
            logGroupAction(db, {
                groupId,
                userId: actorId,
                targetId: targetUserId,
                actionContent: GROUP_LOG_ACTION.MEMBER_DEMOTED,
            })
            return NextResponse.json({ ok: true, action })
        }

        if (action === 'promote_deputy') {
            if (isGroupLeaderRole(targetMembership.role) || isGroupDeputyRole(targetMembership.role)) {
                return NextResponse.json({ ok: false, message: 'Invalid target role' }, { status: 400 })
            }
            await db.run(`UPDATE user_groups SET role = ? WHERE group_id = ? AND user_id = ?`, [
                GROUP_ROLE_DEPUTY,
                groupId,
                targetUserId,
            ])
            void notifyGroupMemberAction(db, {
                groupId,
                action: 'promote_deputy',
                targetUserId,
                actorUserId: actorId,
            }).catch((err) => console.error('[group] notify promote_deputy failed:', err))
            logGroupAction(db, {
                groupId,
                userId: actorId,
                targetId: targetUserId,
                actionContent: GROUP_LOG_ACTION.MEMBER_PROMOTED_DEPUTY,
            })
            return NextResponse.json({ ok: true, action })
        }

        return NextResponse.json({ ok: false, message: 'Invalid action' }, { status: 400 })
    } catch (error: unknown) {
        console.error('Failed to update group member:', error)
        return NextResponse.json(
            { ok: false, message: error instanceof Error ? error.message : 'Failed to update member' },
            { status: 500 }
        )
    }
}

/** 成員自行退出家族（家族長不可使用） */
export async function DELETE(
    request: NextRequest,
    { params }: { params: { id: string; userId: string } }
) {
    try {
        const routeParam = String(params?.id ?? '').trim()
        const targetUserId = String(params?.userId ?? '').trim()
        const actorId = await getUserIdFromRequest(request)

        if (!routeParam || !targetUserId) {
            return NextResponse.json({ ok: false, message: 'Invalid parameters' }, { status: 400 })
        }
        if (!actorId || actorId !== targetUserId) {
            return NextResponse.json({ ok: false, message: 'Forbidden' }, { status: 403 })
        }

        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, targetUserId]
        )
        if (!membership) {
            return NextResponse.json({ ok: false, message: 'Not a member' }, { status: 404 })
        }
        if (isGroupLeaderRole(membership.role)) {
            return NextResponse.json(
                { ok: false, message: 'Family head cannot leave; transfer leadership first' },
                { status: 400 }
            )
        }

        await db.run(`DELETE FROM user_groups WHERE group_id = ? AND user_id = ?`, [
            groupId,
            targetUserId,
        ])

        logGroupAction(db, {
            groupId,
            userId: targetUserId,
            targetId: targetUserId,
            actionContent: GROUP_LOG_ACTION.MEMBER_LEFT,
        })

        return NextResponse.json({ ok: true, action: 'leave' })
    } catch (error: unknown) {
        console.error('Failed to leave group:', error)
        return NextResponse.json(
            { ok: false, message: error instanceof Error ? error.message : 'Failed to leave group' },
            { status: 500 }
        )
    }
}
