import prisma from '~/server/utils/prisma'

export default defineEventHandler(async (event) => {
  try {
    // Check authentication
    const user = event.context.user;
    if (!user || !user.userID) {
      return {
        statusCode: 401,
        body: { success: false, message: 'Unauthorized' }
      }
    }

    const query = getQuery(event)
    const period = query.period || '7d' // Default to last 7 days
    const channel = query.channel || 'all'
    
    // Calculate date range based on selected period
    const endDate = new Date()
    let startDate = new Date()
    
    switch(period) {
      case '1d':
        startDate.setDate(startDate.getDate() - 1)
        break
      case '7d':
        startDate.setDate(startDate.getDate() - 7)
        break
      case '30d':
        startDate.setDate(startDate.getDate() - 30)
        break
      case '90d':
        startDate.setDate(startDate.getDate() - 90)
        break
      case '12m':
        startDate.setMonth(startDate.getMonth() - 12)
        break
      default:
        startDate.setDate(startDate.getDate() - 7)
    }
    
    // Channel filter
    const channelFilter = channel !== 'all' ? { channel_type: channel } : {}
    
    // Get key metrics
    const totalSent = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Sent',
        ...channelFilter
      }
    })
    
    const previousPeriodEnd = new Date(startDate)
    const previousPeriodStart = new Date(startDate)
    
    // Calculate the same duration for previous period
    switch(period) {
      case '1d':
        previousPeriodStart.setDate(previousPeriodStart.getDate() - 1)
        break
      case '7d':
        previousPeriodStart.setDate(previousPeriodStart.getDate() - 7)
        break
      case '30d':
        previousPeriodStart.setDate(previousPeriodStart.getDate() - 30)
        break
      case '90d':
        previousPeriodStart.setDate(previousPeriodStart.getDate() - 90)
        break
      case '12m':
        previousPeriodStart.setMonth(previousPeriodStart.getMonth() - 12)
        break
    }
    
    const previousTotalSent = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: previousPeriodStart,
          lt: startDate
        },
        status: 'Sent',
        ...channelFilter
      }
    })
    
    const sentChangePercent = previousTotalSent > 0 
      ? ((totalSent - previousTotalSent) / previousTotalSent * 100).toFixed(1)
      : '0.0'
    
    // Get success rate
    const totalAttempted = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        action: {
          in: ['Notification Sent', 'Delivery Attempted']
        },
        ...channelFilter
      }
    })
    
    const successfulDeliveries = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Sent',
        ...channelFilter
      }
    })
    
    const successRate = totalAttempted > 0 
      ? ((successfulDeliveries / totalAttempted) * 100).toFixed(1)
      : '0.0'
      
    const previousSuccessRate = await calculateSuccessRate(
      prisma, 
      previousPeriodStart, 
      startDate, 
      channelFilter
    )
    
    const successRateChangePercent = previousSuccessRate > 0
      ? ((parseFloat(successRate) - previousSuccessRate) / previousSuccessRate * 100).toFixed(1)
      : '0.0'
    
    // Get open rate (if tracking available)
    const totalOpened = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Opened',
        ...channelFilter
      }
    })
    
    const openRate = totalSent > 0 
      ? ((totalOpened / totalSent) * 100).toFixed(1)
      : '0.0'
      
    const previousOpenRate = await calculateOpenRate(
      prisma, 
      previousPeriodStart, 
      startDate, 
      channelFilter
    )
    
    const openRateChangePercent = previousOpenRate > 0
      ? ((parseFloat(openRate) - previousOpenRate) / previousOpenRate * 100).toFixed(1)
      : '0.0'
    
    // Get click rate (if tracking available)
    const totalClicked = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Clicked',
        ...channelFilter
      }
    })
    
    const clickRate = totalSent > 0 
      ? ((totalClicked / totalSent) * 100).toFixed(1)
      : '0.0'
      
    const previousClickRate = await calculateClickRate(
      prisma, 
      previousPeriodStart, 
      startDate, 
      channelFilter
    )
    
    const clickRateChangePercent = previousClickRate > 0
      ? ((parseFloat(clickRate) - previousClickRate) / previousClickRate * 100).toFixed(1)
      : '0.0'
    
    // Get channel performance data
    const channelPerformance = await getChannelPerformance(prisma, startDate, endDate)
    
    // Get recent notable events
    const recentEvents = await getRecentEvents(prisma)

    return {
      statusCode: 200,
      body: {
        success: true,
        data: {
          keyMetrics: [
            {
              title: "Total Sent",
              value: totalSent.toLocaleString(),
              icon: "ic:outline-send",
              trend: parseFloat(sentChangePercent) >= 0 ? "up" : "down",
              change: `${parseFloat(sentChangePercent) >= 0 ? '+' : ''}${sentChangePercent}%`
            },
            {
              title: "Success Rate",
              value: `${successRate}%`,
              icon: "ic:outline-check-circle",
              trend: parseFloat(successRateChangePercent) >= 0 ? "up" : "down",
              change: `${parseFloat(successRateChangePercent) >= 0 ? '+' : ''}${successRateChangePercent}%`
            },
            {
              title: "Open Rate",
              value: `${openRate}%`,
              icon: "ic:outline-open-in-new",
              trend: parseFloat(openRateChangePercent) >= 0 ? "up" : "down",
              change: `${parseFloat(openRateChangePercent) >= 0 ? '+' : ''}${openRateChangePercent}%`
            },
            {
              title: "Click Rate",
              value: `${clickRate}%`,
              icon: "ic:outline-touch-app",
              trend: parseFloat(clickRateChangePercent) >= 0 ? "up" : "down",
              change: `${parseFloat(clickRateChangePercent) >= 0 ? '+' : ''}${clickRateChangePercent}%`
            }
          ],
          channelPerformance,
          recentEvents
        }
      }
    }
  } catch (error) {
    console.error('Error fetching analytics data:', error)
    return {
      statusCode: 500,
      body: { success: false, message: 'Failed to fetch analytics data', error: error.message }
    }
  }
})

// Helper functions
async function calculateSuccessRate(prisma, startDate, endDate, channelFilter) {
  const totalAttempted = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      action: {
        in: ['Notification Sent', 'Delivery Attempted']
      },
      ...channelFilter
    }
  })
  
  const successfulDeliveries = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      status: 'Sent',
      ...channelFilter
    }
  })
  
  return totalAttempted > 0 
    ? ((successfulDeliveries / totalAttempted) * 100)
    : 0
}

async function calculateOpenRate(prisma, startDate, endDate, channelFilter) {
  const totalSent = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      status: 'Sent',
      ...channelFilter
    }
  })
  
  const totalOpened = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      status: 'Opened',
      ...channelFilter
    }
  })
  
  return totalSent > 0 
    ? ((totalOpened / totalSent) * 100)
    : 0
}

async function calculateClickRate(prisma, startDate, endDate, channelFilter) {
  const totalSent = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      status: 'Sent',
      ...channelFilter
    }
  })
  
  const totalClicked = await prisma.notification_logs.count({
    where: {
      created_at: {
        gte: startDate,
        lt: endDate
      },
      status: 'Clicked',
      ...channelFilter
    }
  })
  
  return totalSent > 0 
    ? ((totalClicked / totalSent) * 100)
    : 0
}

async function getChannelPerformance(prisma, startDate, endDate) {
  // Define the channels we want to analyze
  const channels = ['Email', 'SMS', 'Push Notification', 'Webhook']
  const channelIcons = {
    'Email': 'ic:outline-email',
    'SMS': 'ic:outline-sms',
    'Push Notification': 'ic:outline-notifications',
    'Webhook': 'ic:outline-webhook'
  }
  
  const result = []
  
  for (const channel of channels) {
    // Get total sent for this channel
    const sent = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Sent',
        channel_type: channel
      }
    })
    
    // Get total failed for this channel
    const failed = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Failed',
        channel_type: channel
      }
    })
    
    // Get total bounced for this channel
    const bounced = await prisma.notification_logs.count({
      where: {
        created_at: {
          gte: startDate,
          lte: endDate
        },
        status: 'Bounced',
        channel_type: channel
      }
    })
    
    // Calculate total attempted (sent + failed + bounced)
    const total = sent + failed + bounced
    
    // Calculate success rate
    const successRate = total > 0 ? ((sent / total) * 100).toFixed(1) : '0.0'
    
    // Calculate bounce rate
    const bounceRate = total > 0 ? ((bounced / total) * 100).toFixed(1) : '0.0'
    
    // Calculate failure rate
    const failureRate = total > 0 ? ((failed / total) * 100).toFixed(1) : '0.0'
    
    result.push({
      name: channel,
      icon: channelIcons[channel] || 'ic:outline-message',
      sent: sent.toString(),
      failed: failed.toString(),
      bounced: bounced.toString(),
      total: total.toString(),
      successRate,
      bounceRate,
      failureRate
    })
  }
  
  return result
}

// Function to get recent notable events
async function getRecentEvents(prisma) {
  // Get last 24 hours
  const now = new Date()
  const oneDayAgo = new Date(now)
  oneDayAgo.setDate(oneDayAgo.getDate() - 1)
  
  // Find recent logs with interesting events
  const recentLogs = await prisma.notification_logs.findMany({
    where: {
      created_at: {
        gte: oneDayAgo,
        lte: now
      },
      OR: [
        { status: 'Failed' },
        { status: 'Bounced' },
        { 
          AND: [
            { status: 'Sent' },
            { 
              details: {
                contains: 'batch'
              } 
            }
          ]
        },
        { status: 'Opened' }
      ]
    },
    orderBy: {
      created_at: 'desc'
    },
    take: 5
  })
  
  // Transform logs into notable events
  return recentLogs.map(log => {
    let type = 'info'
    let title = log.action
    let description = log.details || ''
    let value = ''
    let time = formatTimeAgo(log.created_at)
    
    if (log.status === 'Failed') {
      type = 'error'
      title = 'Delivery Failure'
      description = log.error_message || log.details || ''
      value = log.channel_type || ''
    } else if (log.status === 'Bounced') {
      type = 'warning'
      title = 'Delivery Bounced'
      value = log.channel_type || ''
    } else if (log.status === 'Opened') {
      type = 'success'
      title = 'Notification Opened'
      value = 'User Engagement'
    } else if (log.status === 'Sent' && log.details?.includes('batch')) {
      type = 'info'
      title = 'Batch Delivery'
      // Try to extract batch size from details
      const match = log.details?.match(/(\d+)\s*notifications?/i)
      value = match ? `${match[1]} sent` : ''
    }
    
    return {
      title,
      description,
      value,
      time,
      type
    }
  })
}

// Format time ago
function formatTimeAgo(timestamp) {
  const now = new Date()
  const time = new Date(timestamp)
  const diffInMinutes = Math.floor((now - time) / (1000 * 60))

  if (diffInMinutes < 1) return "Just now"
  if (diffInMinutes < 60) return `${diffInMinutes} minutes ago`
  if (diffInMinutes < 1440) return `${Math.floor(diffInMinutes / 60)} hours ago`
  return `${Math.floor(diffInMinutes / 1440)} days ago`
} 