import prisma from "~/server/utils/prisma";
import { processEmailQueue } from "~/server/utils/emailService";

const ENV = useRuntimeConfig();

// Simple API key auth
function requireApiKey(event) {
  const headers = getRequestHeaders(event);
  const provided = headers["x-api-key"] || headers["X-API-Key"];
  const expected = ENV.notificationApiKey; // Use private runtime config, not public

  if (!expected) {
    throw createError({
      statusCode: 500,
      statusMessage:
        "Notification API is not configured (missing NUXT_NOTIFICATION_API_KEY environment variable)",
    });
  }
  if (!provided || provided !== expected) {
    throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
  }
}

// Basic input validation (aligned with internal create API)
function validateInput(body) {
  const errors = [];
  if (!body?.title?.trim()) errors.push("Title is required");
  if (!body?.type || !["single", "bulk"].includes(body.type))
    errors.push("Type must be either 'single' or 'bulk'");
  if (
    !body?.priority ||
    !["low", "medium", "high", "critical"].includes(body.priority)
  )
    errors.push("Invalid priority");
  if (!body?.category?.trim()) errors.push("Category is required");
  if (!Array.isArray(body?.channels) || body.channels.length === 0)
    errors.push("At least one channel is required");
  else {
    const validChannels = ["email", "push", "sms"];
    const invalid = body.channels.filter((c) => !validChannels.includes(c));
    if (invalid.length) errors.push(`Invalid channels: ${invalid.join(", ")}`);
  }
  if (
    !body?.deliveryType ||
    !["immediate", "scheduled"].includes(body.deliveryType)
  )
    errors.push("Invalid deliveryType");
  if (
    !body?.audienceType ||
    !["all", "specific", "segmented"].includes(body.audienceType)
  )
    errors.push("Invalid audienceType");
  if (!body?.contentType || !["new", "template"].includes(body.contentType))
    errors.push("Invalid contentType");
  if (body.deliveryType === "scheduled" && !body.scheduledAt)
    errors.push("scheduledAt is required for scheduled delivery");
  if (body.channels?.includes("email") && !body.emailSubject)
    errors.push("emailSubject is required when using email channel");
  if (body.contentType === "template" && !body.selectedTemplate)
    errors.push("selectedTemplate is required for template content");
  if (body.contentType === "new") {
    if (body.channels?.includes("email") && !body.emailContent)
      errors.push("emailContent is required for email channel");
    if (body.channels?.includes("push") && (!body.pushTitle || !body.pushBody))
      errors.push("pushTitle and pushBody required for push channel");
  }
  if (body.audienceType === "specific") {
    if (!Array.isArray(body.specificUsers) || body.specificUsers.length === 0)
      errors.push(
        "specificUsers must be a non-empty array for specific audience"
      );
  }
  if (
    body.audienceType === "segmented" &&
    (!Array.isArray(body.userSegments) || body.userSegments.length === 0)
  )
    errors.push("At least one user segment is required");
  return errors;
}

export default defineEventHandler(async (event) => {
  try {
    requireApiKey(event);

    const body = await readBody(event);
    const validationErrors = validateInput(body);
    if (validationErrors.length > 0) {
      throw createError({
        statusCode: 400,
        statusMessage: "Validation failed",
        data: { errors: validationErrors },
      });
    }

    const notificationData = {
      title: body.title,
      type: body.type,
      priority: body.priority,
      category: body.category,
      channels: body.channels,
      emailSubject: body.emailSubject || null,
      deliveryType: body.deliveryType,
      scheduledAt: body.scheduledAt || null,
      timezone: body.timezone || "UTC",
      audienceType: body.audienceType,
      specificUsers: body.specificUsers || null,
      userSegments: body.userSegments || [],
      excludeUnsubscribed: body.excludeUnsubscribed !== false,
      contentType: body.contentType,
      selectedTemplate: body.selectedTemplate || null,
      emailContent: body.emailContent || null,
      callToActionText: body.callToActionText || null,
      callToActionUrl: body.callToActionUrl || null,
      pushTitle: body.pushTitle || null,
      pushBody: body.pushBody || null,
    };

    const result = await prisma.$transaction(async (tx) => {
      // Category
      const category = await tx.notification_categories.findFirst({
        where: { value: notificationData.category },
      });
      if (!category) {
        throw createError({
          statusCode: 400,
          statusMessage: "Invalid category",
        });
      }

      // Template (if any)
      let templateData = null;
      if (notificationData.contentType === "template") {
        templateData = await tx.notification_templates.findFirst({
          where: { value: notificationData.selectedTemplate, is_active: true },
        });
        if (!templateData)
          throw createError({
            statusCode: 400,
            statusMessage: "Invalid or inactive template",
          });
      }

      // Estimate audience size (simple heuristic matching internal API)
      let estimatedReach = 0;
      if (notificationData.audienceType === "all")
        estimatedReach = 1; // demo default
      else if (
        notificationData.audienceType === "specific" &&
        notificationData.specificUsers
      ) {
        estimatedReach = Array.isArray(notificationData.specificUsers)
          ? notificationData.specificUsers.length
          : notificationData.specificUsers.split("\n").filter((l) => l.trim()).length;
      } else if (notificationData.audienceType === "segmented") {
        estimatedReach = notificationData.userSegments?.length || 0;
      }

      // Create notification
      const notification = await tx.notifications.create({
        data: {
          title: notificationData.title,
          type: notificationData.type,
          priority: notificationData.priority,
          category_id: category.id,
          delivery_type: notificationData.deliveryType,
          scheduled_at: notificationData.scheduledAt
            ? new Date(notificationData.scheduledAt)
            : null,
          timezone: notificationData.timezone,
          enable_tracking: true,
          audience_type: notificationData.audienceType,
          specific_users: Array.isArray(notificationData.specificUsers)
            ? notificationData.specificUsers.join("\n")
            : notificationData.specificUsers,
          exclude_unsubscribed: notificationData.excludeUnsubscribed,
          respect_do_not_disturb: true,
          content_type: notificationData.contentType,
          template_id: templateData?.id || null,
          email_subject:
            notificationData.emailSubject || templateData?.subject || null,
          email_content:
            notificationData.emailContent ||
            templateData?.email_content ||
            null,
          call_to_action_text: notificationData.callToActionText || null,
          call_to_action_url: notificationData.callToActionUrl || null,
          push_title:
            notificationData.pushTitle || templateData?.push_title || null,
          push_body:
            notificationData.pushBody || templateData?.push_body || null,
          estimated_reach: estimatedReach,
          created_by: "public-api",
          status:
            notificationData.deliveryType === "immediate"
              ? "sending"
              : "scheduled",
        },
      });

      // Channels
      await tx.notification_channels.createMany({
        data: notificationData.channels.map((c) => ({
          notification_id: notification.id,
          channel_type: c,
        })),
      });

      // Segments
      if (
        notificationData.audienceType === "segmented" &&
        notificationData.userSegments?.length > 0
      ) {
        for (const seg of notificationData.userSegments) {
          const segRow = await tx.user_segments.findFirst({
            where: { value: seg, is_active: true },
          });
          if (segRow) {
            await tx.notification_user_segments.create({
              data: { notification_id: notification.id, segment_id: segRow.id },
            });
          }
        }
      }

      // Recipients list (demo-friendly)
      const recipients = [];
      if (notificationData.audienceType === "all") {
        const senderEmail = process.env.SMTP_USER || "test@example.com";
        recipients.push({ user_id: "public-user-1", email: senderEmail });
      } else if (
        notificationData.audienceType === "specific" &&
        notificationData.specificUsers
      ) {
        const ids = Array.isArray(notificationData.specificUsers)
          ? notificationData.specificUsers
          : notificationData.specificUsers.split("\n").map((l) => l.trim()).filter(Boolean);
        for (const id of ids) {
          const isEmail = id.includes("@");
          recipients.push({
            user_id: isEmail ? id.split("@")[0] : id,
            email: isEmail ? id : `${id}@example.com`,
          });
        }
      } else if (notificationData.audienceType === "segmented") {
        for (let i = 0; i < (notificationData.userSegments?.length || 0); i++) {
          const segVal = notificationData.userSegments[i];
          recipients.push({
            user_id: `${segVal}-user-${i + 1}`,
            email: `${segVal}${i + 1}@example.com`,
          });
        }
      }

      // Create recipients + queue using batch inserts for better performance
      console.log(`📦 Processing ${recipients.length} recipients across ${notificationData.channels.length} channel(s)...`);

      // Prepare batch data for recipients
      const recipientsData = [];
      for (const r of recipients) {
        for (const ch of notificationData.channels) {
          recipientsData.push({
            notification_id: notification.id,
            user_id: r.user_id,
            email: ch === "email" ? r.email : null,
            channel_type: ch,
            status: "pending",
          });
        }
      }

      // Batch insert all recipients at once
      await tx.notification_recipients.createMany({
        data: recipientsData,
      });

      // Fetch created recipients to get their IDs for queue
      const createdRecipients = await tx.notification_recipients.findMany({
        where: { notification_id: notification.id },
        orderBy: { id: 'asc' }
      });

      // Prepare batch data for queue
      let scheduledFor;
      if (notificationData.deliveryType === "immediate")
        scheduledFor = new Date(Date.now() + 60000);
      else if (notificationData.scheduledAt)
        scheduledFor = new Date(notificationData.scheduledAt);
      else scheduledFor = new Date(Date.now() + 300000);

      const priority = notificationData.priority === "critical" ? 1
                     : notificationData.priority === "high" ? 2
                     : notificationData.priority === "medium" ? 3
                     : 5;

      const queueData = createdRecipients.map(rec => ({
        notification_id: notification.id,
        recipient_id: rec.id,
        scheduled_for: scheduledFor,
        priority,
        status: "queued",
      }));

      // Batch insert all queue items at once
      await tx.notification_queue.createMany({
        data: queueData,
      });

      console.log(`✅ Created ${createdRecipients.length} recipients and queue items in batch`);

      return {
        id: notification.id,
        estimatedReach,
        recipientsCreated: createdRecipients.length,
      };
    });

    // Process queue in background (non-blocking)
    if (body.deliveryType === "immediate") {
      // Don't await - let it run in background
      processEmailQueue().catch(err => {
        console.error('Background queue processing error:', err);
      });
    }

    return {
      success: true,
      data: {
        id: result.id,
        message:
          body.deliveryType === "immediate"
            ? "Notification queued for immediate delivery"
            : "Notification has been scheduled",
        estimatedReach: result.estimatedReach,
        recipientsQueued: result.recipientsCreated || 0,
      },
    };
  } catch (error) {
    console.log("Error:", error);

    if (error.statusCode) throw error;
    throw createError({
      statusCode: 500,
      statusMessage: "Failed to create notification",
      data: { error: error.message },
    });
  } finally {
  }
});
