import { NextRequest, NextResponse } from 'next/server'
import { getDb } from '@/server/db'
import { getUserIdFromCookie, validateSession } from '@/app/api/_helpers/session'

function formatRelativeTime(createdAt: string): { value: number; unit: 'just' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year' } {
    const now = new Date()
    const created = new Date(createdAt)
    const diffMs = now.getTime() - created.getTime()
    const diffSeconds = Math.floor(diffMs / 1000)
    const diffMinutes = Math.floor(diffSeconds / 60)
    const diffHours = Math.floor(diffMinutes / 60)
    const diffDays = Math.floor(diffHours / 24)
    const diffWeeks = Math.floor(diffDays / 7)
    const diffMonths = Math.floor(diffDays / 30)
    const diffYears = Math.floor(diffDays / 365)

    if (diffSeconds < 60) {
        return { value: 0, unit: 'just' }
    } else if (diffMinutes < 60) {
        return { value: diffMinutes, unit: 'minute' }
    } else if (diffHours < 24) {
        return { value: diffHours, unit: 'hour' }
    } else if (diffDays < 7) {
        return { value: diffDays, unit: 'day' }
    } else if (diffWeeks < 4) {
        return { value: diffWeeks, unit: 'week' }
    } else if (diffMonths < 12) {
        return { value: diffMonths, unit: 'month' }
    } else {
        return { value: diffYears, unit: 'year' }
    }
}

function buildNestedComments(
    flatComments: Array<{
        id: string
        userId: string
        author: string
        avatar: string | null
        content: string
        likes: number
        parentId: string | null
        replyTo: string | null
        isPinned: number
        createdAt: string
        editedAt: string | null
    }>,
    videoOwnerName: string | null = null,
    likedComments: Set<string> = new Set()
): Array<{
    id: string
    userId: string
    author: string
    avatar: string
    content: string
    time: string
    likes: number
    replies?: number
    isPinned?: boolean
    pinnedBy?: string | null
    isLiked?: boolean
    replyTo?: string
    nestedReplies?: any[]
    isEdited?: boolean
}> {
    // 創建 ID 到留言的映射
    const commentMap = new Map<string, any>()
    const rootComments: any[] = []

    // 第一遍：創建所有留言對象
    flatComments.forEach((comment) => {
        const timeData = formatRelativeTime(comment.createdAt)
        const commentObj = {
            id: comment.id,
            userId: comment.userId,
            author: comment.author,
            avatar: comment.avatar || '',
            content: comment.content,
            time: timeData,
            likes: comment.likes,
            isPinned: Boolean(comment.isPinned),
            pinnedBy: comment.isPinned ? videoOwnerName : null,
            isLiked: likedComments.has(comment.id),
            replyTo: comment.replyTo || undefined,
            nestedReplies: [] as any[],
            isEdited: Boolean(comment.editedAt),
        }
        commentMap.set(comment.id, commentObj)
    })

    // 計算留言的深度（從根留言開始，根留言深度為 0）
    function getCommentDepth(commentId: string, visited: Set<string> = new Set()): number {
        if (visited.has(commentId)) return 0 // 防止循環引用
        visited.add(commentId)
        
        const comment = flatComments.find(c => c.id === commentId)
        if (!comment || !comment.parentId) return 0 // 根留言，深度為 0
        
        return getCommentDepth(comment.parentId, visited) + 1
    }

    // 找到指定深度的父留言 ID
    function findParentAtDepth(commentId: string, targetDepth: number): string | null {
        const comment = flatComments.find(c => c.id === commentId)
        if (!comment) return null
        
        const depth = getCommentDepth(commentId)
        if (depth === targetDepth) return commentId
        if (!comment.parentId) return null
        
        return findParentAtDepth(comment.parentId, targetDepth)
    }

    // 第二遍：構建嵌套結構（限制最多三層）
    flatComments.forEach((comment) => {
        const commentObj = commentMap.get(comment.id)!
        if (comment.parentId) {
            // 這是回覆，檢查深度
            const depth = getCommentDepth(comment.id)
            if (depth >= 3) {
                // 超過第三層，找到第二層的父留言（第三層的留言），將其作為第三層的平級回覆
                const thirdLevelParentId = findParentAtDepth(comment.id, 2)
                
                if (thirdLevelParentId) {
                    const thirdLevelParent = commentMap.get(thirdLevelParentId)
                    if (thirdLevelParent) {
                        // 確保 replyTo 指向原始要回覆的留言作者
                        const originalParent = commentMap.get(comment.parentId)
                        if (originalParent) {
                            commentObj.replyTo = originalParent.author
                        }
                        thirdLevelParent.nestedReplies.push(commentObj)
                    }
                } else {
                    // 如果找不到第三層父留言，作為根留言處理（不應該發生，但作為後備）
                    rootComments.push(commentObj)
                }
            } else {
                // 三層以內，正常添加到父留言的 nestedReplies
                const parent = commentMap.get(comment.parentId)
                if (parent) {
                    parent.nestedReplies.push(commentObj)
                }
            }
        } else {
            // 這是根留言
            rootComments.push(commentObj)
        }
    })

    // 第三遍：計算回覆數量並排序（置頂優先，然後按時間）
    function processComment(comment: any) {
        if (comment.nestedReplies && comment.nestedReplies.length > 0) {
            comment.replies = comment.nestedReplies.length
            // 遞歸處理嵌套回覆
            comment.nestedReplies.forEach(processComment)
            // 按時間排序嵌套回覆（最新的在前）
            comment.nestedReplies.sort((a: any, b: any) => {
                const aComment = flatComments.find(c => c.id === a.id)
                const bComment = flatComments.find(c => c.id === b.id)
                const aTime = aComment?.createdAt || ''
                const bTime = bComment?.createdAt || ''
                return new Date(bTime).getTime() - new Date(aTime).getTime()
            })
        }
    }

    rootComments.forEach(processComment)

    // 排序根留言：置頂優先，然後按時間
    rootComments.sort((a, b) => {
        if (a.isPinned && !b.isPinned) return -1
        if (!a.isPinned && b.isPinned) return 1
        const aTime = flatComments.find(c => c.id === a.id)?.createdAt || ''
        const bTime = flatComments.find(c => c.id === b.id)?.createdAt || ''
        return new Date(bTime).getTime() - new Date(aTime).getTime()
    })

    return rootComments
}

export async function GET(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const catchId = String(params?.id ?? '')
        const db = await getDb()
        const sessionUserId = await getUserIdFromCookie()

        const videoOwner = await db.get<{ userId: string; displayName: string }>(
            `SELECT c.user_id AS userId, u.display_name AS displayName 
             FROM catch c
             LEFT JOIN users u ON c.user_id = u.user_id
             WHERE c.catch_id = ?`,
            [catchId]
        )

        const rawComments = await db.all<{
            id: string
            userId: string
            author: string
            avatar: string | null
            content: string
            likes: number
            parentId: string | null
            replyTo: string | null
            isPinned: number
            created_at_sec: number
            edited_at_sec: number | null
        }>(
            `SELECT 
                cc.comment_id AS id,
                cc.user_id AS userId,
                u.display_name AS author,
                u.avatar_url AS avatar,
                cc.contents AS content,
                (SELECT COUNT(1) FROM catch_comment_likes ccl WHERE ccl.comment_id = cc.comment_id) AS likes,
                cc.parent_id AS parentId,
                cc.reply_to AS replyTo,
                cc.is_pinned AS isPinned,
                cc.created_at AS created_at_sec,
                cc.edited_at AS edited_at_sec
            FROM catch_comments cc
            LEFT JOIN users u ON cc.user_id = u.user_id
            WHERE cc.catch_id = ?
            ORDER BY cc.created_at ASC`,
            [catchId]
        ) || []

        const comments = (Array.isArray(rawComments) ? rawComments : []).map((c) => ({
            id: c.id,
            userId: c.userId,
            author: c.author,
            avatar: c.avatar,
            content: c.content,
            likes: c.likes,
            parentId: c.parentId,
            replyTo: c.replyTo,
            isPinned: c.isPinned,
            createdAt: new Date(c.created_at_sec * 1000).toISOString(),
            editedAt:
                c.edited_at_sec != null && Number(c.edited_at_sec) > 0
                    ? new Date(Number(c.edited_at_sec) * 1000).toISOString()
                    : null,
        }))

        const commentIds = comments.map((c) => c.id)
        let likedComments = new Set<string>()
        if (sessionUserId && commentIds.length > 0) {
            const placeholders = commentIds.map(() => '?').join(',')
            const liked = await db.all<{ comment_id: string }>(
                `SELECT comment_id FROM catch_comment_likes WHERE comment_id IN (${placeholders}) AND user_id = ?`,
                [...commentIds, sessionUserId]
            )
            likedComments = new Set(Array.isArray(liked) ? liked.map((l) => l.comment_id) : [])
        }

        const nestedComments = buildNestedComments(
            comments,
            videoOwner?.displayName || null,
            likedComments
        )

        return NextResponse.json({
            ok: true,
            data: nestedComments,
        })
    } catch (error: any) {
        console.error('Failed to fetch comments:', error)
        return NextResponse.json(
            { ok: false, message: error?.message || 'Failed to fetch comments' },
            { status: 500 }
        )
    }
}

export async function POST(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const catchId = String(params?.id ?? '')
        const userId = await validateSession(request)

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

        const body = await request.json()
        const { content, parentId, replyTo } = body

        if (!content) {
            return NextResponse.json(
                { ok: false, error: 'MISSING_FIELDS' },
                { status: 400 }
            )
        }

        const db = await getDb()

        const user = await db.get<{ displayName: string }>(
            `SELECT display_name AS displayName FROM users WHERE user_id = ?`,
            [userId]
        )

        if (!user) {
            return NextResponse.json(
                { ok: false, error: 'USER_NOT_FOUND' },
                { status: 404 }
            )
        }

        // 生成唯一 ID
        const commentId = `comment-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`

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

        await db.run(
            `INSERT INTO catch_comments (comment_id, catch_id, user_id, contents, parent_id, reply_to, is_pinned, created_at, edited_at)
            VALUES (?, ?, ?, ?, ?, ?, 0, ?, NULL)`,
            [commentId, catchId, userId, content, parentId || null, replyTo || null, nowSec]
        )

        await db.run(`UPDATE catch SET updated_at = ? WHERE catch_id = ?`, [nowSec, catchId])

        const newComment = await db.get<{
            id: string
            author: string
            avatar: string | null
            content: string
            likes: number
            parentId: string | null
            replyTo: string | null
            isPinned: number
            created_at_sec: number
        }>(
            `SELECT 
                cc.comment_id AS id,
                u.display_name AS author,
                u.avatar_url AS avatar,
                cc.contents AS content,
                (SELECT COUNT(1) FROM catch_comment_likes ccl WHERE ccl.comment_id = cc.comment_id) AS likes,
                cc.parent_id AS parentId,
                cc.reply_to AS replyTo,
                cc.is_pinned AS isPinned,
                cc.created_at AS created_at_sec
            FROM catch_comments cc
            LEFT JOIN users u ON cc.user_id = u.user_id
            WHERE cc.comment_id = ?`,
            [commentId]
        )

        if (!newComment) {
            return NextResponse.json(
                { ok: false, error: 'FAILED_TO_CREATE' },
                { status: 500 }
            )
        }

        const timeData = formatRelativeTime(new Date(newComment.created_at_sec * 1000).toISOString())
        return NextResponse.json({
            ok: true,
            data: {
                id: newComment.id,
                author: newComment.author,
                avatar: newComment.avatar || '',
                content: newComment.content,
                time: timeData,
                likes: newComment.likes,
                replyTo: newComment.replyTo || undefined,
            },
        })
    } catch (error: any) {
        console.error('Failed to create comment:', error)
        return NextResponse.json(
            { ok: false, message: error?.message || 'Failed to create comment' },
            { status: 500 }
        )
    }
}

export async function DELETE(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const catchId = String(params?.id ?? '')
        const userId = await validateSession(request)

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

        const { searchParams } = new URL(request.url)
        const commentId = searchParams.get('commentId')

        if (!commentId) {
            return NextResponse.json(
                { ok: false, error: 'MISSING_COMMENT_ID' },
                { status: 400 }
            )
        }

        const db = await getDb()

        const comment = await db.get<{
            userId: string
            catchId: string
        }>(
            `SELECT user_id AS userId, catch_id AS catchId FROM catch_comments WHERE comment_id = ?`,
            [commentId]
        )

        if (!comment) {
            return NextResponse.json(
                { ok: false, error: 'COMMENT_NOT_FOUND' },
                { status: 404 }
            )
        }

        if (comment.catchId !== catchId) {
            return NextResponse.json(
                { ok: false, error: 'FORBIDDEN' },
                { status: 403 }
            )
        }

        const catchVideo = await db.get<{ userId: string | number }>(
            `SELECT user_id AS userId FROM catch WHERE catch_id = ?`,
            [catchId]
        )

        if (!catchVideo) {
            return NextResponse.json(
                { ok: false, error: 'VIDEO_NOT_FOUND' },
                { status: 404 }
            )
        }

        // 確保類型一致（都轉換為字符串進行比較）
        const videoOwnerId = String(catchVideo.userId).trim()
        const commentOwnerId = String(comment.userId).trim()
        const currentUserId = String(userId).trim()

        const isVideoOwner = videoOwnerId === currentUserId
        const isCommentOwner = commentOwnerId === currentUserId

        if (!isCommentOwner && !isVideoOwner) {
            return NextResponse.json(
                { ok: false, error: 'FORBIDDEN' },
                { status: 403 }
            )
        }

        const childCommentsResult = await db.all<{ id: string }>(
            `WITH RECURSIVE child_comments AS (
                SELECT comment_id AS id FROM catch_comments WHERE parent_id = ?
                UNION ALL
                SELECT cc.comment_id AS id FROM catch_comments cc
                INNER JOIN child_comments ch ON cc.parent_id = ch.id
            )
            SELECT id FROM child_comments`,
            [commentId]
        )
        const childComments: Array<{ id: string }> = Array.isArray(childCommentsResult) ? childCommentsResult : []

        // 計算要刪除的留言總數（父留言 + 所有子留言）
        const totalDeletedCount = 1 + childComments.length

        // 如果有子留言，先刪除所有子留言
        if (childComments.length > 0) {
            const childCommentIds = childComments.map((c: { id: string }) => c.id)
            const placeholders = childCommentIds.map(() => '?').join(',')
            await db.run(
                `DELETE FROM catch_comments WHERE comment_id IN (${placeholders})`,
                childCommentIds
            )
        }

        // 刪除父留言
        await db.run(
            `DELETE FROM catch_comments WHERE comment_id = ?`,
            [commentId]
        )

        await db.run(`UPDATE catch SET updated_at = ? WHERE catch_id = ?`, [
            Math.floor(Date.now() / 1000),
            comment.catchId,
        ])

        return NextResponse.json({
            ok: true,
            message: 'Comment deleted successfully',
        })
    } catch (error: any) {
        console.error('Failed to delete comment:', error)
        return NextResponse.json(
            { ok: false, message: error?.message || 'Failed to delete comment' },
            { status: 500 }
        )
    }
}

export async function PATCH(
    request: NextRequest,
    { params }: { params: { id: string } }
) {
    try {
        const catchId = String(params?.id ?? '')
        const userId = await validateSession(request)

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

        const body = await request.json()
        const { commentId, isPinned } = body

        if (!commentId || typeof isPinned !== 'boolean') {
            return NextResponse.json(
                { ok: false, error: 'MISSING_FIELDS' },
                { status: 400 }
            )
        }

        const db = await getDb()

        const catchVideo = await db.get<{ userId: string | number }>(
            `SELECT user_id AS userId FROM catch WHERE catch_id = ?`,
            [catchId]
        )

        if (!catchVideo) {
            return NextResponse.json(
                { ok: false, error: 'VIDEO_NOT_FOUND' },
                { status: 404 }
            )
        }

        // 確保類型一致（都轉換為字符串進行比較）
        const videoOwnerId = String(catchVideo.userId).trim()
        const currentUserId = String(userId).trim()

        if (videoOwnerId !== currentUserId) {
            return NextResponse.json(
                { ok: false, error: 'FORBIDDEN' },
                { status: 403 }
            )
        }

        const comment = await db.get<{ id: string; parentId: string | null }>(
            `SELECT comment_id AS id, parent_id AS parentId FROM catch_comments WHERE comment_id = ? AND catch_id = ?`,
            [commentId, catchId]
        )

        if (!comment) {
            return NextResponse.json(
                { ok: false, error: 'COMMENT_NOT_FOUND' },
                { status: 404 }
            )
        }

        // 只有父留言（parentId 為 null）才能置頂
        if (isPinned && comment.parentId !== null) {
            return NextResponse.json(
                { ok: false, error: 'CANNOT_PIN_REPLY' },
                { status: 400 }
            )
        }

        if (isPinned) {
            await db.run(
                `UPDATE catch_comments SET is_pinned = 0 WHERE catch_id = ? AND comment_id != ? AND parent_id IS NULL`,
                [catchId, commentId]
            )
        }

        await db.run(
            `UPDATE catch_comments SET is_pinned = ? WHERE comment_id = ?`,
            [isPinned ? 1 : 0, commentId]
        )

        return NextResponse.json({
            ok: true,
            data: { commentId, isPinned },
        })
    } catch (error: any) {
        console.error('Failed to pin/unpin comment:', error)
        return NextResponse.json(
            { ok: false, message: error?.message || 'Failed to pin/unpin comment' },
            { status: 500 }
        )
    }
}

