/**
 * 🌳 TREE TRIGGER — connects appointment events to reminder trees
 *
 * Called whenever an appointment is created / completed / no-showed.
 * Finds the matching active tree and starts (or resumes) a UserJourney.
 */

import { prisma } from "./db";
import { ReminderTreeEngine } from "./reminder-tree-engine";
import { sendMessage } from "./waha";

export type TriggerType = "booking_created" | "no_show" | "completed" | "custom";

/**
 * Fire the tree that matches `triggerType` for this appointment's clinic.
 * Non-blocking — caller should await in the background (fire-and-forget).
 */
export async function triggerTree(
  appointmentId: string,
  triggerType: TriggerType
): Promise<{ started: boolean; treeId?: string; treeName?: string; journeyId?: string; error?: string }> {
  try {
    // 1. Load appointment + clinic
    const appointment = await prisma.appointment.findUnique({
      where: { id: appointmentId },
      include: { clinic: true, lead: true, treatment: true },
    });
    if (!appointment) return { started: false, error: "Appointment not found" };

    console.log(`🌳 triggerTree(${triggerType}) for ${appointment.lead.name} [${appointment.lead.phone}]`);

    // 2. Find active trees matching trigger for this clinic, ordered by id (CUID = chronological)
    const trees = await prisma.reminderTree.findMany({
      where: { clinicId: appointment.clinicId, triggerType, isActive: true },
      orderBy: { id: "asc" },
    });

    if (!trees.length) {
      console.log(`🌳 No active "${triggerType}" tree found`);
      return { started: false, error: `No active tree for trigger: ${triggerType}` };
    }

    // 3. Pick the first tree that has an executable root node (not just a 'start' placeholder)
    let chosenTree = trees[0];
    for (const t of trees) {
      const root = await prisma.treeNode.findFirst({
        where: { treeId: t.id, parentId: null },
        orderBy: { sortOrder: "asc" },
      });
      // Prefer trees whose root can actually send something
      if (root && !["start", "end"].includes(root.nodeType ?? "")) {
        chosenTree = t;
        break;
      }
    }

    const tree = chosenTree;

    // 4. Verify root node exists
    const rootNode = await prisma.treeNode.findFirst({
      where: { treeId: tree.id, parentId: null },
      orderBy: { sortOrder: "asc" },
    });
    if (!rootNode) {
      console.error(`❌ Tree "${tree.name}" (${tree.id}) has no root node — skipping`);

      // Persist alert in DB so dashboard can surface it
      try {
        await prisma.cronLog.create({
          data: {
            type: "tree-error",
            error: `Tree "${tree.name}" has no root node and could not start for appointment ${appointmentId}. Please check the Reminder Trees page.`,
            durationMs: 0,
          },
        });
      } catch { /* non-critical */ }

      return { started: false, error: "Tree has no root node" };
    }

    // 5. Check for existing active journey (avoid duplicates)
    const existing = await prisma.userJourney.findFirst({
      where: { appointmentId, treeId: tree.id, status: "active" },
    });
    if (existing) {
      console.log(`🔄 Journey already active for appointment ${appointmentId}`);
      return { started: true, treeId: tree.id, treeName: tree.name, journeyId: existing.id };
    }

    console.log(`🚀 Starting tree "${tree.name}" (${triggerType}) — root: [${rootNode.nodeType}] ${rootNode.name}`);

    // 6. Start the journey — this sends the first message immediately
    const journey = await ReminderTreeEngine.startJourney(appointmentId, tree.id, triggerType);

    console.log(`✅ Journey ${journey.id} started`);
    return { started: true, treeId: tree.id, treeName: tree.name, journeyId: journey.id };

  } catch (err: any) {
    console.error("❌ triggerTree error:", err.message ?? err);
    return { started: false, error: err.message ?? String(err) };
  }
}

/**
 * Called when an incoming WhatsApp message arrives — advances active journeys.
 */
export async function handlePatientReply(
  phone: string,
  message: string,
  _clinicId: string  // kept for signature compat — we search globally
): Promise<boolean> {
  try {
    const cleanPhone = phone.replace(/\D/g, "");
    const last9 = cleanPhone.slice(-9);

    // Find active journeys directly by phone — skips the clinic mismatch problem
    const journeys = await prisma.userJourney.findMany({
      where: {
        status: "active",
        appointment: {
          lead: { phone: { contains: last9 } },
        },
      },
      include: {
        appointment: { include: { lead: true, clinic: true, treatment: true } },
        currentNode: true,
      },
      orderBy: { lastActiveAt: "desc" },
      take: 1,
    });

    if (!journeys.length) {
      console.log(`🔍 No active tree journey for phone …${last9}`);
      return false;
    }

    const journey = journeys[0];
    console.log(`📨 Patient reply "${message.slice(0, 60)}" → journey ${journey.id} | node [${journey.currentNode?.nodeType}] ${journey.currentNode?.name}`);

    await ReminderTreeEngine.handleUserResponse(journey.appointmentId, message);
    return true;

  } catch (err: any) {
    console.error("❌ handlePatientReply error:", err.message);
    return false;
  }
}

/**
 * Direct WAHA fallback — sends a plain booking confirmation when no tree is active.
 */
export async function sendDirectBookingConfirmation(appointmentId: string): Promise<void> {
  try {
    const apt = await prisma.appointment.findUnique({
      where: { id: appointmentId },
      include: { lead: true, treatment: true, clinic: true },
    });
    if (!apt) return;

    const tz = apt.clinic.timezone || "Asia/Riyadh";
    const apptDate = new Date(apt.dateTime);
    const dateStr = new Intl.DateTimeFormat("en-US", {
      timeZone: tz, weekday: "long", month: "long", day: "numeric",
    }).format(apptDate);
    const timeStr = new Intl.DateTimeFormat("en-US", {
      timeZone: tz, hour: "numeric", minute: "2-digit", hour12: true,
    }).format(apptDate);

    const firstName = apt.lead.name.split(" ")[0];
    const confirmUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/api/confirm/${apt.id}?token=${apt.confirmToken}`;

    const message = `📅 *Appointment Confirmed!*

Hi ${firstName}! ✅

Your *${apt.treatment.name}* appointment is confirmed:

📅 ${dateStr}
🕐 ${timeStr}
🏥 ${apt.clinic.name}

Please confirm your attendance:
${confirmUrl}

Reply *YES* to confirm or *CANCEL* to cancel.

We look forward to seeing you! 🌟`;

    console.log(`📤 Sending direct booking confirmation to ${apt.lead.phone}`);
    await sendMessage(apt.lead.phone, message);

    // Log it
    await prisma.messageLog.create({
      data: {
        clinicId: apt.clinicId,
        appointmentId: apt.id,
        phone: apt.lead.phone,
        direction: "outgoing",
        message,
        status: "sent",
        sentAt: new Date(),
      },
    });
    console.log(`✅ Direct booking confirmation sent to ${apt.lead.phone}`);
  } catch (err: any) {
    console.error("❌ sendDirectBookingConfirmation failed:", err.message);
  }
}
