import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { isAdmin } from '@/lib/admin'

export async function GET(request: NextRequest) {
  try {
    const session = await auth()

    if (!session?.user?.email || !isAdmin(session.user.email)) {
      return NextResponse.json(
        { success: false, error: 'Unauthorized - Admin only' },
        { status: 403 }
      )
    }

    const searchParams = request.nextUrl.searchParams
    const page = parseInt(searchParams.get('page') || '1')
    const limit = Math.min(parseInt(searchParams.get('limit') || '50'), 100) // Max 100
    const search = searchParams.get('search') || ''
    const cursor = searchParams.get('cursor') || '' // cursor = last ID for fast pagination

    let shortLinks: { id: bigint; code: string | null; link: string | null; created_at: Date; updated_at: Date }[] = []
    let totalCount = 0
    let hasMore = false

    if (search) {
      const searchPattern = `%${search}%`

      // For search, use OFFSET (unavoidable) but limit search to reasonable results
      const offset = (page - 1) * limit

      shortLinks = await prisma.$queryRaw<{ id: bigint; code: string | null; link: string | null; created_at: Date; updated_at: Date }[]>`
        SELECT id, code, link, created_at, updated_at
        FROM short_links
        WHERE deleted_at IS NULL
          AND (code LIKE ${searchPattern} OR link LIKE ${searchPattern})
        ORDER BY id DESC
        LIMIT ${limit + 1} OFFSET ${offset}
      `

      // Check if has more
      hasMore = shortLinks.length > limit
      if (hasMore) shortLinks = shortLinks.slice(0, limit)

      // Get count with search (cached or estimated for large datasets)
      const countResult = await prisma.$queryRaw<{ count: bigint }[]>`
        SELECT COUNT(*) as count FROM short_links
        WHERE deleted_at IS NULL
          AND (code LIKE ${searchPattern} OR link LIKE ${searchPattern})
      `
      totalCount = Number(countResult[0]?.count || 0)
    } else {
      // Use cursor-based pagination for non-search (much faster for large datasets)
      if (cursor) {
        const cursorId = BigInt(cursor)
        shortLinks = await prisma.$queryRaw<{ id: bigint; code: string | null; link: string | null; created_at: Date; updated_at: Date }[]>`
          SELECT id, code, link, created_at, updated_at
          FROM short_links
          WHERE deleted_at IS NULL AND id < ${cursorId}
          ORDER BY id DESC
          LIMIT ${limit + 1}
        `
      } else {
        // First page or offset-based
        if (page === 1) {
          shortLinks = await prisma.$queryRaw<{ id: bigint; code: string | null; link: string | null; created_at: Date; updated_at: Date }[]>`
            SELECT id, code, link, created_at, updated_at
            FROM short_links
            WHERE deleted_at IS NULL
            ORDER BY id DESC
            LIMIT ${limit + 1}
          `
        } else {
          // For jumping to specific page, use optimized OFFSET
          const offset = (page - 1) * limit
          shortLinks = await prisma.$queryRaw<{ id: bigint; code: string | null; link: string | null; created_at: Date; updated_at: Date }[]>`
            SELECT id, code, link, created_at, updated_at
            FROM short_links
            WHERE deleted_at IS NULL
            ORDER BY id DESC
            LIMIT ${limit + 1} OFFSET ${offset}
          `
        }
      }

      // Check if has more
      hasMore = shortLinks.length > limit
      if (hasMore) shortLinks = shortLinks.slice(0, limit)

      // Get total count (use approximate count for very large tables)
      const countResult = await prisma.$queryRaw<{ count: bigint }[]>`
        SELECT COUNT(*) as count FROM short_links WHERE deleted_at IS NULL
      `
      totalCount = Number(countResult[0]?.count || 0)
    }

    // Get next cursor (last ID in current result)
    const nextCursor = shortLinks.length > 0 ? String(shortLinks[shortLinks.length - 1].id) : null

    // Format response
    const formattedLinks = shortLinks.map(link => ({
      id: String(link.id),
      code: link.code,
      link: link.link,
      createdAt: link.created_at,
      updatedAt: link.updated_at,
    }))

    return NextResponse.json({
      success: true,
      data: {
        shortLinks: formattedLinks,
        pagination: {
          page,
          limit,
          total: totalCount,
          totalPages: Math.ceil(totalCount / limit),
          hasMore,
          nextCursor,
        },
      },
    })
  } catch (error) {
    console.error('Admin shortlinks error:', error)
    return NextResponse.json(
      { success: false, error: `Failed to fetch shortlinks: ${error instanceof Error ? error.message : String(error)}` },
      { status: 500 }
    )
  }
}

export async function PUT(request: NextRequest) {
  try {
    const session = await auth()

    if (!session?.user?.email || !isAdmin(session.user.email)) {
      return NextResponse.json(
        { success: false, error: 'Unauthorized - Admin only' },
        { status: 403 }
      )
    }

    const { id, code, link } = await request.json()

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

    if (!code || !link) {
      return NextResponse.json(
        { success: false, error: 'Code and link are required' },
        { status: 400 }
      )
    }

    // Validate code format (alphanumeric, dash, underscore, 1-50 chars)
    if (!/^[a-zA-Z0-9_-]+$/.test(code) || code.length > 50) {
      return NextResponse.json(
        { success: false, error: 'Invalid code format' },
        { status: 400 }
      )
    }

    // Validate URL
    try {
      new URL(link)
    } catch {
      return NextResponse.json(
        { success: false, error: 'Invalid URL format' },
        { status: 400 }
      )
    }

    // Check if code already exists (exclude current ID)
    const existing = await prisma.$queryRaw<{ id: bigint }[]>`
      SELECT id FROM short_links
      WHERE code = ${code}
      AND deleted_at IS NULL
      AND id != ${BigInt(id)}
      LIMIT 1
    `

    if (existing.length > 0) {
      return NextResponse.json(
        { success: false, error: 'Code already exists' },
        { status: 400 }
      )
    }

    // Update shortlink
    const now = new Date()
    await prisma.$executeRaw`
      UPDATE short_links
      SET code = ${code}, link = ${link}, updated_at = ${now}
      WHERE id = ${BigInt(id)} AND deleted_at IS NULL
    `

    return NextResponse.json({
      success: true,
      message: 'Shortlink updated successfully',
    })
  } catch (error) {
    console.error('Admin update shortlink error:', error)
    return NextResponse.json(
      { success: false, error: `Failed to update shortlink: ${error instanceof Error ? error.message : String(error)}` },
      { status: 500 }
    )
  }
}

export async function DELETE(request: NextRequest) {
  try {
    const session = await auth()

    if (!session?.user?.email || !isAdmin(session.user.email)) {
      return NextResponse.json(
        { success: false, error: 'Unauthorized - Admin only' },
        { status: 403 }
      )
    }

    const { ids } = await request.json()

    if (!ids || !Array.isArray(ids) || ids.length === 0) {
      return NextResponse.json(
        { success: false, error: 'No IDs provided' },
        { status: 400 }
      )
    }

    // Soft delete - process each ID individually
    const now = new Date()
    for (const id of ids) {
      await prisma.$executeRaw`
        UPDATE short_links
        SET deleted_at = ${now}
        WHERE id = ${BigInt(id)}
      `
    }

    return NextResponse.json({
      success: true,
      message: `${ids.length} shortlink(s) deleted`,
    })
  } catch (error) {
    console.error('Admin delete shortlinks error:', error)
    return NextResponse.json(
      { success: false, error: `Failed to delete shortlinks: ${error instanceof Error ? error.message : String(error)}` },
      { status: 500 }
    )
  }
}
