import { NextRequest, NextResponse } from 'next/server'
import { getDb } from '@/server/db'
import { getUserIdFromRequest } from '@/app/api/_helpers/session'
import {
    applyLiveInputSyncToRoomStream,
    fetchCloudflareLiveInput,
    mapLiveInputToRoomStreamFields,
    parseLiveInputApiId,
} from '@/lib/streams/cloudflareLiveInput'
import {
    parseRoomStreamCategory,
    serializeRoomStreamCategory,
} from '@/lib/streams/roomStreamCategory'
import {
    parseRoomStreamAttribute,
    serializeRoomStreamAttribute,
} from '@/lib/streams/roomStreamAttribute'
import { resolveStreamPublishUrl } from '@/lib/streams/cloudflareStreamUrls'

export async function POST(request: NextRequest) {
    try {
        const userId = await getUserIdFromRequest(request)

        if (!userId) {
            return NextResponse.json(
                { ok: false, error: 'Unauthorized' },
                { status: 401 }
            )
        }

        const body = await request.json()
        const { roomId, title, description, category, attribute, thumbnail } = body

        if (!roomId) {
            return NextResponse.json(
                { ok: false, error: 'Room ID is required' },
                { status: 400 }
            )
        }

        if (roomId !== userId) {
            return NextResponse.json(
                { ok: false, error: 'Forbidden' },
                { status: 403 }
            )
        }

        const db = await getDb()
        const stream = await db.get<{
            room_id: string
            live_input_identifier: string | null
            started_at: number | null
        }>(
            `SELECT room_id, live_input_identifier, started_at FROM room_streams WHERE room_id = ?`,
            [roomId]
        )

        const titleVal = String(title ?? '').trim()
        const descriptionVal = String(description ?? '').trim()
        const thumbnailVal = String(thumbnail ?? '').trim()
        const categoryVal = serializeRoomStreamCategory(parseRoomStreamCategory(category))
        const attributeVal = serializeRoomStreamAttribute(parseRoomStreamAttribute(attribute))

        /** 串流金鑰僅能由 create-live-input 建立，此 API 不允許變更 */
        const liveInputToWrite = stream
            ? String(stream.live_input_identifier ?? '').trim() || null
            : null

        const nowSec = Math.floor(Date.now() / 1000)

        if (!stream) {
            await db.run(
                `INSERT INTO room_streams (
                    room_id,
                    title,
                    description,
                    category,
                    attribute,
                    thumbnail_url,
                    live_input_identifier,
                    chat_disabled,
                    stream_status,
                    created_at,
                    updated_at
                ) VALUES (?, ?, ?, ?, ?, ?, ?, 0, 'disconnected', ?, ?)`,
                [
                    roomId,
                    titleVal,
                    descriptionVal || null,
                    categoryVal,
                    attributeVal,
                    thumbnailVal,
                    liveInputToWrite,
                    nowSec,
                    nowSec,
                ]
            )
        } else {
            await db.run(
                `UPDATE room_streams
                 SET title = ?,
                     description = ?,
                     category = ?,
                     attribute = ?,
                     thumbnail_url = ?,
                     live_input_identifier = ?,
                     updated_at = ?
                 WHERE room_id = ?`,
                [
                    titleVal,
                    descriptionVal || null,
                    categoryVal,
                    attributeVal,
                    thumbnailVal,
                    liveInputToWrite,
                    nowSec,
                    roomId,
                ]
            )
        }

        let webrtcPublishUrl: string | null = null
        let cloudflareError: string | null = null

        if (liveInputToWrite) {
            const apiId = parseLiveInputApiId(liveInputToWrite)
            if (!apiId) {
                return NextResponse.json(
                    { ok: false, error: 'Cannot resolve Cloudflare live input id' },
                    { status: 400 }
                )
            }

            const fetched = await fetchCloudflareLiveInput(apiId)
            if (fetched.ok) {
                const sync = mapLiveInputToRoomStreamFields(fetched.result, {
                    titleFallback: titleVal,
                })
                webrtcPublishUrl =
                    resolveStreamPublishUrl(liveInputToWrite) ||
                    sync.webrtc_publish_url

                if (sync.title) {
                    await db.run(
                        `UPDATE room_streams SET title = COALESCE(NULLIF(?, ''), title) WHERE room_id = ?`,
                        [sync.title, roomId]
                    )
                }

                await applyLiveInputSyncToRoomStream(db, roomId, fetched.result, {
                    titleFallback: titleVal,
                    nowSec,
                })
            } else {
                cloudflareError = fetched.error
                console.error('[dashboard/update] Cloudflare live input fetch failed:', fetched.error)
            }
        }

        return NextResponse.json({
            ok: true,
            liveInputIdentifier: liveInputToWrite ?? '',
            streamKey: liveInputToWrite ?? '',
            webrtcPublishUrl,
            cloudflareError,
        })
    } catch (error: unknown) {
        console.error('Failed to update stream settings:', error)
        return NextResponse.json(
            {
                ok: false,
                error: error instanceof Error ? error.message : 'Failed to update stream settings',
            },
            { status: 500 }
        )
    }
}
