import { NextResponse } from "next/server";
import { prisma } from "@/lib/db";
import { getSession } from "@/lib/auth";

/**
 * Upgrade #10: Appointment Outcome Analytics + ROI Tracking
 *
 * Returns:
 * - No-show rate trends (weekly)
 * - Confirmation rate by trigger (which reminder gets the most confirms?)
 * - Average response time
 * - Revenue saved estimate (no-shows prevented × avg treatment price)
 * - Reminder effectiveness breakdown
 * - Delivery/read rates
 */
export async function GET() {
  const session = await getSession();
  if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });

  const clinicId = session.id;
  const now = new Date();
  const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60_000);
  const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60_000);
  const sixtyDaysAgo = new Date(now.getTime() - 60 * 24 * 60 * 60_000);

  // ─── 1. Overall appointment stats ───────────────────────────
  const [
    totalAppointments30d,
    confirmedCount,
    completedCount,
    noShowCount,
    cancelledCount,
    totalAppointmentsPrev30d,
    noShowCountPrev30d,
  ] = await Promise.all([
    prisma.appointment.count({
      where: { clinicId, createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, status: "confirmed", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, status: "completed", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, status: "no_show", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, status: "cancelled", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, createdAt: { gte: sixtyDaysAgo, lt: thirtyDaysAgo } },
    }),
    prisma.appointment.count({
      where: { clinicId, status: "no_show", createdAt: { gte: sixtyDaysAgo, lt: thirtyDaysAgo } },
    }),
  ]);

  const attendedCount = completedCount + confirmedCount;
  const decisiveCount = attendedCount + noShowCount;

  const noShowRate30d = decisiveCount > 0 ? Math.round((noShowCount / decisiveCount) * 100) : 0;
  const prevDecisive = (totalAppointmentsPrev30d - cancelledCount) || 1;
  const noShowRatePrev = prevDecisive > 0 ? Math.round((noShowCountPrev30d / prevDecisive) * 100) : 0;
  const noShowRateChange = noShowRate30d - noShowRatePrev;

  // ─── 2. Reminder effectiveness (which triggers get confirms?) ──
  const sentReminders = await prisma.scheduledReminder.findMany({
    where: {
      status: "sent",
      sentAt: { gte: thirtyDaysAgo },
      appointment: { clinicId },
    },
    include: {
      template: { select: { trigger: true } },
      appointment: { select: { status: true, confirmedAt: true } },
    },
  });

  // Group by trigger
  const triggerStats: Record<string, { sent: number; confirmed: number; trigger: string }> = {};
  for (const r of sentReminders) {
    const trigger = r.template?.trigger || "unknown";
    if (!triggerStats[trigger]) {
      triggerStats[trigger] = { sent: 0, confirmed: 0, trigger };
    }
    triggerStats[trigger].sent++;

    // If appointment was confirmed after this reminder was sent
    if (
      r.appointment.status === "confirmed" ||
      r.appointment.status === "completed" ||
      r.appointment.status === "arrived"
    ) {
      if (r.appointment.confirmedAt && r.sentAt && r.appointment.confirmedAt >= r.sentAt) {
        triggerStats[trigger].confirmed++;
      }
    }
  }

  const reminderEffectiveness = Object.values(triggerStats)
    .map((s) => ({
      ...s,
      confirmRate: s.sent > 0 ? Math.round((s.confirmed / s.sent) * 100) : 0,
    }))
    .sort((a, b) => b.confirmRate - a.confirmRate);

  // ─── 3. Message delivery/read rates ─────────────────────────
  const [msgSent, msgDelivered, msgRead, msgFailed] = await Promise.all([
    prisma.messageLog.count({
      where: { clinicId, direction: "outgoing", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.messageLog.count({
      where: { clinicId, direction: "outgoing", status: "delivered", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.messageLog.count({
      where: { clinicId, direction: "outgoing", status: "read", createdAt: { gte: thirtyDaysAgo } },
    }),
    prisma.messageLog.count({
      where: { clinicId, direction: "outgoing", status: "failed", createdAt: { gte: thirtyDaysAgo } },
    }),
  ]);

  const deliveryRate = msgSent > 0 ? Math.round(((msgDelivered + msgRead) / msgSent) * 100) : 0;
  const readRate = msgSent > 0 ? Math.round((msgRead / msgSent) * 100) : 0;

  // ─── 4. Average response time ──────────────────────────────
  // Find pairs: outgoing message → first incoming response from same phone
  const recentOutgoing = await prisma.messageLog.findMany({
    where: {
      clinicId,
      direction: "outgoing",
      createdAt: { gte: sevenDaysAgo },
      sentAt: { not: null },
    },
    select: { phone: true, sentAt: true },
    orderBy: { sentAt: "desc" },
    take: 100,
  });

  const responseTimes: number[] = [];
  const checkedPhones = new Set<string>();

  for (const out of recentOutgoing) {
    if (!out.sentAt || checkedPhones.has(out.phone)) continue;
    checkedPhones.add(out.phone);

    const response = await prisma.messageLog.findFirst({
      where: {
        clinicId,
        phone: out.phone,
        direction: "incoming",
        createdAt: { gt: out.sentAt },
      },
      select: { createdAt: true },
      orderBy: { createdAt: "asc" },
    });

    if (response) {
      const diffMin = (response.createdAt.getTime() - out.sentAt.getTime()) / 60_000;
      if (diffMin > 0 && diffMin < 24 * 60) { // Within 24 hours
        responseTimes.push(diffMin);
      }
    }
  }

  const avgResponseMin = responseTimes.length > 0
    ? Math.round(responseTimes.reduce((a, b) => a + b, 0) / responseTimes.length)
    : null;

  // ─── 5. Revenue impact / ROI ────────────────────────────────
  // Calculate average treatment price
  const treatments = await prisma.treatment.findMany({
    where: { clinicId, isActive: true, price: { not: null } },
    select: { price: true },
  });

  const avgPrice = treatments.length > 0
    ? treatments.reduce((s, t) => s + (t.price || 0), 0) / treatments.length
    : 0;

  // Estimate: if previous no-show rate was 30% and now it's 10%,
  // the improvement × appointment count × avg price = revenue saved
  const noShowsPrevented = Math.max(0, Math.round(
    (noShowRatePrev / 100) * decisiveCount - noShowCount
  ));
  const estimatedRevenueSaved = Math.round(noShowsPrevented * avgPrice);

  // Total reminders sent vs. total failed permanently
  const [totalRemindersSent, totalRemindersFailed] = await Promise.all([
    prisma.scheduledReminder.count({
      where: { status: "sent", appointment: { clinicId } },
    }),
    prisma.scheduledReminder.count({
      where: { status: "failed", retryCount: { gte: 3 }, appointment: { clinicId } },
    }),
  ]);

  const reminderSuccessRate = (totalRemindersSent + totalRemindersFailed) > 0
    ? Math.round((totalRemindersSent / (totalRemindersSent + totalRemindersFailed)) * 100)
    : 100;

  // ─── 6. Weekly trend (last 4 weeks) ────────────────────────
  const weeklyTrend: { week: string; appointments: number; noShows: number; confirmed: number }[] = [];
  for (let i = 3; i >= 0; i--) {
    const weekStart = new Date(now.getTime() - (i + 1) * 7 * 24 * 60 * 60_000);
    const weekEnd = new Date(now.getTime() - i * 7 * 24 * 60 * 60_000);

    const [appts, noShows, confirmed] = await Promise.all([
      prisma.appointment.count({
        where: { clinicId, dateTime: { gte: weekStart, lt: weekEnd } },
      }),
      prisma.appointment.count({
        where: { clinicId, status: "no_show", dateTime: { gte: weekStart, lt: weekEnd } },
      }),
      prisma.appointment.count({
        where: {
          clinicId,
          status: { in: ["confirmed", "completed", "arrived"] },
          dateTime: { gte: weekStart, lt: weekEnd },
        },
      }),
    ]);

    weeklyTrend.push({
      week: weekStart.toLocaleDateString("en-US", { month: "short", day: "numeric" }),
      appointments: appts,
      noShows,
      confirmed,
    });
  }

  return NextResponse.json({
    period: "30 days",

    appointments: {
      total: totalAppointments30d,
      confirmed: confirmedCount,
      completed: completedCount,
      noShows: noShowCount,
      cancelled: cancelledCount,
      noShowRate: noShowRate30d,
      noShowRateChange,
      noShowRateTrend: noShowRateChange < 0 ? "improving" : noShowRateChange > 0 ? "worsening" : "stable",
    },

    reminders: {
      totalSent: totalRemindersSent,
      totalFailed: totalRemindersFailed,
      successRate: reminderSuccessRate,
      effectiveness: reminderEffectiveness,
    },

    messaging: {
      sent: msgSent,
      delivered: msgDelivered,
      read: msgRead,
      failed: msgFailed,
      deliveryRate,
      readRate,
    },

    engagement: {
      avgResponseMinutes: avgResponseMin,
      avgResponseFormatted: avgResponseMin
        ? avgResponseMin < 60
          ? `${avgResponseMin} min`
          : `${Math.round(avgResponseMin / 60)}h ${avgResponseMin % 60}m`
        : "N/A",
      uniqueRespondents: checkedPhones.size,
      responseCount: responseTimes.length,
    },

    roi: {
      avgTreatmentPrice: Math.round(avgPrice),
      noShowsPrevented,
      estimatedRevenueSaved,
      noShowRateImprovement: -noShowRateChange,
    },

    weeklyTrend,
  });
}
