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

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

    // Debug: log session info
    console.log('Admin stats - Session:', JSON.stringify(session, null, 2))
    console.log('Admin stats - Email:', session?.user?.email)
    console.log('Admin stats - isAdmin:', session?.user?.email ? isAdmin(session.user.email) : false)

    // Check if user is authenticated and is admin
    if (!session?.user?.email || !isAdmin(session.user.email)) {
      return NextResponse.json(
        { success: false, error: `Unauthorized - Admin only. Your email: ${session?.user?.email || 'not logged in'}` },
        { status: 403 }
      )
    }

    const now = new Date()
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
    const yesterday = new Date(today)
    yesterday.setDate(yesterday.getDate() - 1)
    const last7Days = new Date(today)
    last7Days.setDate(last7Days.getDate() - 7)
    const last30Days = new Date(today)
    last30Days.setDate(last30Days.getDate() - 30)
    const lastWeekStart = new Date(today)
    lastWeekStart.setDate(lastWeekStart.getDate() - 14)
    const lastWeekEnd = new Date(today)
    lastWeekEnd.setDate(lastWeekEnd.getDate() - 7)

    // Get total users
    const totalUsers = await prisma.user.count()
    console.log('Total users:', totalUsers)

    // Get total short links (using raw query to handle mixed ID types)
    const totalShortLinksResult = await prisma.$queryRaw<{ count: bigint }[]>`
      SELECT COUNT(*) as count FROM short_links WHERE deleted_at IS NULL
    `
    const totalShortLinks = Number(totalShortLinksResult[0]?.count || 0)

    // Debug: Log short links count
    console.log('Total short links query result:', totalShortLinksResult)
    console.log('Total short links:', totalShortLinks)

    // Get total microsites
    const totalMicrosites = await prisma.microsite.count()

    // Get total microsite links (for click tracking)
    const totalMicrositeLinks = await prisma.micrositeLink.count()

    // Get total clicks on microsite links
    const clickStats = await prisma.micrositeLink.aggregate({
      _sum: {
        clicks: true,
      },
    })

    // ========================================
    // GROWTH STATISTICS
    // ========================================

    // Users today
    const usersToday = await prisma.user.count({
      where: {
        createdAt: { gte: today }
      }
    })

    // Users this week
    const usersThisWeek = await prisma.user.count({
      where: {
        createdAt: { gte: last7Days }
      }
    })

    // Users last week (for comparison)
    const usersLastWeek = await prisma.user.count({
      where: {
        createdAt: {
          gte: lastWeekStart,
          lt: lastWeekEnd
        }
      }
    })

    // Short links today (using raw query with proper DATE casting)
    const linksTodayResult = await prisma.$queryRaw<{ count: bigint }[]>`
      SELECT COUNT(*) as count FROM short_links
      WHERE deleted_at IS NULL AND DATE(created_at) >= DATE(${today.toISOString().split('T')[0]})
    `
    const linksToday = Number(linksTodayResult[0]?.count || 0)
    console.log('Links today query result:', linksTodayResult, 'Date:', today.toISOString())

    // Short links this week (using raw query with proper DATE casting)
    const linksThisWeekResult = await prisma.$queryRaw<{ count: bigint }[]>`
      SELECT COUNT(*) as count FROM short_links
      WHERE deleted_at IS NULL AND created_at >= ${last7Days.toISOString()}
    `
    const linksThisWeek = Number(linksThisWeekResult[0]?.count || 0)
    console.log('Links this week query result:', linksThisWeekResult, 'Date:', last7Days.toISOString())

    // Microsites today
    const micrositesToday = await prisma.microsite.count({
      where: {
        createdAt: { gte: today }
      }
    })

    // Microsites this week
    const micrositesThisWeek = await prisma.microsite.count({
      where: {
        createdAt: { gte: last7Days }
      }
    })

    // ========================================
    // DAILY ACTIVITY (Last 30 days)
    // ========================================

    // Format daily data helper
    const formatDailyData = (raw: { date: string | Date; count: bigint }[]) => {
      // Create map with strict YYYY-MM-DD string keys
      const dataMap = new Map(raw.map(r => {
        let dateStr: string;
        if (r.date instanceof Date) {
          dateStr = r.date.toISOString().split('T')[0];
        } else {
          dateStr = String(r.date).split('T')[0]; // Handle string case just in case
        }
        return [dateStr, Number(r.count)]
      }))

      const result: { date: string; count: number }[] = []
      for (let i = 29; i >= 0; i--) {
        const d = new Date(today)
        d.setDate(d.getDate() - i)
        // Ensure we generate the same YYYY-MM-DD format for lookup
        // Using local time components to match 'today' logic at start of function
        // (Assuming 'today' was constructed from local components)

        // However, 'today' was constructed as: new Date(now.getFullYear()...)
        // which creates a local date at 00:00:00.
        // toISOString() uses UTC.
        // If we want to match the DB's DATE() function (which is likely UTC), we should use UTC for the key.

        // Let's rely on the fact that we constructed 'today' relative to local time, 
        // but we want the keys to match. 
        // Best approach: Use a timezone-offset adjusted ISO string or manually construct YYYY-MM-DD.

        const offset = d.getTimezoneOffset()
        const localDate = new Date(d.getTime() - (offset * 60 * 1000))
        const dateStr = localDate.toISOString().split('T')[0]

        result.push({
          date: dateStr,
          count: dataMap.get(dateStr) || 0
        })
      }
      return result
    }

    let dailyLinks: { date: string; count: number }[] = []
    let dailyUsers: { date: string; count: number }[] = []
    let dailyMicrosites: { date: string; count: number }[] = []

    try {
      const dailyLinksRaw = await prisma.$queryRaw<{ date: string; count: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count
        FROM short_links
        WHERE deleted_at IS NULL AND created_at >= ${last30Days.toISOString()}
        GROUP BY DATE(created_at)
        ORDER BY date ASC
      `
      console.log('Daily links raw data:', dailyLinksRaw)
      dailyLinks = formatDailyData(dailyLinksRaw)
    } catch (e) {
      console.error('Error fetching daily links:', e)
      dailyLinks = formatDailyData([])
    }

    try {
      const dailyUsersRaw = await prisma.$queryRaw<{ date: string; count: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count
        FROM users
        WHERE created_at >= ${last30Days.toISOString()}
        GROUP BY DATE(created_at)
        ORDER BY date ASC
      `
      console.log('Daily users raw data:', dailyUsersRaw)
      dailyUsers = formatDailyData(dailyUsersRaw)
    } catch (e) {
      console.error('Error fetching daily users:', e)
      dailyUsers = formatDailyData([])
    }

    try {
      const dailyMicrositesRaw = await prisma.$queryRaw<{ date: string; count: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count
        FROM microsites
        WHERE created_at >= ${last30Days.toISOString()}
        GROUP BY DATE(created_at)
        ORDER BY date ASC
      `
      console.log('Daily microsites raw data:', dailyMicrositesRaw)
      dailyMicrosites = formatDailyData(dailyMicrositesRaw)
    } catch (e) {
      console.error('Error fetching daily microsites:', e)
      dailyMicrosites = formatDailyData([])
    }

    // ========================================
    // TOP MICROSITES BY CLICKS
    // ========================================

    const topMicrosites = await prisma.microsite.findMany({
      take: 5,
      orderBy: {
        links: {
          _count: 'desc'
        }
      },
      include: {
        user: {
          select: {
            name: true,
            email: true,
            image: true,
          },
        },
        links: {
          select: {
            clicks: true
          }
        },
        _count: {
          select: {
            links: true,
          },
        },
      },
    })

    const topMicrositesWithClicks = topMicrosites.map(site => ({
      id: site.id,
      slug: site.slug,
      title: site.title,
      theme: site.theme,
      user: site.user,
      linksCount: site._count.links,
      totalClicks: site.links.reduce((sum, link) => sum + link.clicks, 0),
      createdAt: site.createdAt,
    })).sort((a, b) => b.totalClicks - a.totalClicks)

    // ========================================
    // USERS WITH MOST MICROSITES
    // ========================================

    const topUsers = await prisma.user.findMany({
      take: 5,
      orderBy: {
        microsites: {
          _count: 'desc'
        }
      },
      select: {
        id: true,
        name: true,
        email: true,
        image: true,
        createdAt: true,
        _count: {
          select: {
            microsites: true,
          },
        },
      },
    })

    // ========================================
    // RECENT ACTIVITY
    // ========================================

    // Get recent users (last 10)
    const recentUsers = await prisma.user.findMany({
      take: 10,
      orderBy: {
        createdAt: 'desc',
      },
      select: {
        id: true,
        name: true,
        email: true,
        image: true,
        createdAt: true,
        _count: {
          select: {
            microsites: true,
          },
        },
      },
    })

    // Get recent short links (last 10) - using raw query to handle mixed ID types
    let recentShortLinks: { id: string; code: string | null; link: string | null; createdAt: Date }[] = []
    try {
      const recentShortLinksRaw = await prisma.$queryRaw<{ id: string | bigint; code: string | null; link: string | null; created_at: Date }[]>`
        SELECT id, code, link, created_at
        FROM short_links
        WHERE deleted_at IS NULL
        ORDER BY created_at DESC
        LIMIT 10
      `
      recentShortLinks = recentShortLinksRaw.map(link => ({
        id: String(link.id),
        code: link.code,
        link: link.link,
        createdAt: link.created_at,
      }))
    } catch (e) {
      console.error('Error fetching recent short links:', e)
    }

    // Get recent microsites (last 10)
    const recentMicrosites = await prisma.microsite.findMany({
      take: 10,
      orderBy: {
        createdAt: 'desc',
      },
      include: {
        user: {
          select: {
            name: true,
            email: true,
          },
        },
        _count: {
          select: {
            links: true,
          },
        },
      },
    })

    // ========================================
    // VISITOR STATISTICS
    // ========================================

    // Total unique visitors (count by IP)
    const totalVisitors = await prisma.visitor.groupBy({
      by: ['ip'],
      _count: true
    }).then(result => result.length)

    // Today's visitors
    const todayVisitors = await prisma.visitor.groupBy({
      by: ['ip'],
      where: {
        visitedAt: { gte: today }
      },
      _count: true
    }).then(result => result.length)

    // Yesterday's visitors (for comparison)
    const yesterdayVisitors = await prisma.visitor.groupBy({
      by: ['ip'],
      where: {
        visitedAt: {
          gte: yesterday,
          lt: today
        }
      },
      _count: true
    }).then(result => result.length)

    // This week visitors
    const thisWeekVisitors = await prisma.visitor.groupBy({
      by: ['ip'],
      where: {
        visitedAt: { gte: last7Days }
      },
      _count: true
    }).then(result => result.length)

    // Last week visitors (for comparison)
    const lastWeekVisitors = await prisma.visitor.groupBy({
      by: ['ip'],
      where: {
        visitedAt: {
          gte: lastWeekStart,
          lt: last7Days
        }
      },
      _count: true
    }).then(result => result.length)

    // Daily visitors for last 30 days
    const dailyVisitors = await prisma.$queryRaw<{ date: string; count: bigint }[]>`
      SELECT DATE(visited_at) as date, COUNT(DISTINCT ip) as count
      FROM visitors
      WHERE visited_at >= ${last30Days.toISOString()}
      GROUP BY DATE(visited_at)
      ORDER BY date ASC
    `
    console.log('Daily visitors raw data:', dailyVisitors)

    // Format daily data to ensure all 30 days are included
    const dailyVisitorData = []
    for (let i = 29; i >= 0; i--) {
      const d = new Date(today)
      d.setDate(d.getDate() - i)
      const dateStr = d.toISOString().split('T')[0]
      const dayData = dailyVisitors.find(v => v.date === dateStr)
      dailyVisitorData.push({
        date: dateStr,
        count: Number(dayData?.count || 0)
      })
    }

    // Top pages visited
    const topPages = await prisma.visitor.groupBy({
      by: ['path'],
      where: {
        path: { not: null },
        visitedAt: { gte: last30Days }
      },
      _count: true,
      orderBy: {
        _count: {
          path: 'desc'
        }
      },
      take: 10
    })

    // Visitor growth percentage
    const visitorGrowthPercent = lastWeekVisitors > 0
      ? Math.round(((thisWeekVisitors - lastWeekVisitors) / lastWeekVisitors) * 100)
      : thisWeekVisitors > 0 ? 100 : 0

    // ========================================
    // SYSTEM HEALTH (active sessions, etc)
    // ========================================

    const activeSessions = await prisma.session.count({
      where: {
        expires: { gt: now }
      }
    })

    // Password protected microsites
    const protectedMicrosites = await prisma.microsite.count({
      where: {
        password: { not: null }
      }
    })

    return NextResponse.json({
      success: true,
      data: {
        stats: {
          totalUsers,
          totalShortLinks,
          totalMicrosites,
          totalMicrositeLinks,
          totalClicks: clickStats._sum.clicks || 0,
        },
        growth: {
          usersToday,
          usersThisWeek,
          usersLastWeek,
          linksToday,
          linksThisWeek,
          micrositesToday,
          micrositesThisWeek,
          userGrowthPercent: usersLastWeek > 0
            ? Math.round(((usersThisWeek - usersLastWeek) / usersLastWeek) * 100)
            : usersThisWeek > 0 ? 100 : 0,
        },
        dailyActivity: {
          links: dailyLinks,
          users: dailyUsers,
          microsites: dailyMicrosites,
        },
        visitorStats: {
          totalVisitors,
          todayVisitors,
          yesterdayVisitors,
          thisWeekVisitors,
          lastWeekVisitors,
          visitorGrowthPercent,
          dailyVisitors: dailyVisitorData,
          topPages: topPages.map(page => ({
            path: page.path,
            visits: page._count
          }))
        },
        topMicrosites: topMicrositesWithClicks,
        topUsers,
        recentUsers,
        recentShortLinks,
        recentMicrosites,
        systemHealth: {
          activeSessions,
          protectedMicrosites,
        },
      },
    })
  } catch (error) {
    console.error('Admin stats error:', error)
    return NextResponse.json(
      { success: false, error: `Failed to fetch admin stats: ${error instanceof Error ? error.message : String(error)}` },
      { status: 500 }
    )
  }
}
