/**
 * Tests for Voice Booking API
 *
 * Tests the /api/bookings/voice endpoint
 */

import { NextRequest } from "next/server";

// Mock dependencies
jest.mock("@/lib/db");

jest.mock("@/lib/logger", () => ({
  logger: {
    info: jest.fn(),
    warn: jest.fn(),
    error: jest.fn(),
  },
}));

jest.mock("@paralleldrive/cuid2", () => ({
  createId: jest.fn(() => "cuid-test-id-12345678"),
}));

jest.mock("@/lib/dual-database", () => ({
  saveBookingToBoth: jest.fn().mockResolvedValue(undefined),
}));

jest.mock("@/lib/utils/organization-data", () => ({
  getEffectiveOwnerId: jest.fn((userId: string) => Promise.resolve(userId)),
}));

jest.mock("@/lib/utils/calendar-sync", () => ({
  syncBookingToCalendar: jest.fn().mockResolvedValue(undefined),
}));

// Route not yet implemented - imports skipped
let POST: any;
import { prisma } from "@/lib/db";

// Voice agent routes not yet implemented
describe.skip("POST /api/bookings/voice", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    // Set current date for testing
    jest.useFakeTimers();
    jest.setSystemTime(new Date("2024-01-15T10:00:00Z"));
  });

  afterEach(() => {
    jest.useRealTimers();
  });

  const createRequest = (body: Record<string, unknown>) => {
    return new NextRequest("http://localhost/api/bookings/voice", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
    });
  };

  it("should return 400 if required fields are missing", async () => {
    const request = createRequest({});
    const response = await POST(request);

    expect(response.status).toBe(400);
    const data = await response.json();
    expect(data.error).toBe("Invalid booking data");
  });

  it("should return 400 if date format is invalid", async () => {
    const request = createRequest({
      date: "invalid-date",
      time: "10:00",
      service: "Checkup",
      patient_name: "John Doe",
      patient_phone: "+1234567890",
    });

    const response = await POST(request);

    expect(response.status).toBe(400);
    const data = await response.json();
    expect(data.error).toBe("Invalid booking data");
  });

  it("should return 400 if booking date is in the past", async () => {
    (prisma.users.findFirst as jest.Mock).mockResolvedValue({
      id: "user-1",
    });

    const request = createRequest({
      date: "2024-01-10", // Before mock current date
      time: "10:00",
      service: "Checkup",
      patient_name: "John Doe",
      patient_phone: "+1234567890",
      agent_id: "agent-123",
    });

    const response = await POST(request);

    expect(response.status).toBe(400);
    const data = await response.json();
    expect(data.error).toBe("Cannot book appointments in the past");
  });

  it("should return 400 if phone number is missing", async () => {
    (prisma.users.findFirst as jest.Mock).mockResolvedValue({
      id: "user-1",
    });

    const request = createRequest({
      date: "2024-01-20",
      time: "10:00",
      service: "Checkup",
      patient_name: "John Doe",
      agent_id: "agent-123",
    });

    const response = await POST(request);

    expect(response.status).toBe(400);
    const data = await response.json();
    expect(data.error).toBe("Patient phone number is required");
  });

  it("should return 400 if user cannot be identified", async () => {
    (prisma.users.findFirst as jest.Mock).mockResolvedValue(null);

    const request = createRequest({
      date: "2024-01-20",
      time: "10:00",
      service: "Checkup",
      patient_name: "John Doe",
      patient_phone: "+1234567890",
      agent_id: "agent-123",
    });

    const response = await POST(request);

    expect(response.status).toBe(400);
    const data = await response.json();
    expect(data.error).toBe("Unable to identify clinic for booking");
  });

  it("should create booking successfully", async () => {
    (prisma.users.findFirst as jest.Mock).mockResolvedValue({
      id: "user-1",
    });

    (prisma.bookings.create as jest.Mock).mockResolvedValue({
      id: "booking-123",
      userId: "user-1",
      customerName: "John Doe",
      customerPhone: "+1234567890",
      customerEmail: null,
      service: "Dental Checkup",
      appointmentDate: new Date("2024-01-20T10:00:00Z"),
      appointmentTime: "10:00",
      duration: 30,
      staffMember: null,
      depositAmount: null,
      depositPaid: false,
      totalAmount: 0,
      status: "pending",
      source: "phone_call",
      notes: null,
    });

    const request = createRequest({
      date: "2024-01-20",
      time: "10:00",
      service: "Dental Checkup",
      patient_name: "John Doe",
      patient_phone: "+1234567890",
      agent_id: "agent-123",
      conversation_id: "conv-456",
    });

    const response = await POST(request);

    expect(response.status).toBe(200);
    const data = await response.json();

    expect(data.success).toBe(true);
    expect(data.booking).toBeDefined();
    expect(data.booking.patient_name).toBe("John Doe");
    expect(data.booking.service).toBe("Dental Checkup");
    expect(data.booking.status).toBe("pending");
    expect(data.message).toContain("John Doe");
    expect(data.message).toContain("2024-01-20");
    expect(data.message).toContain("pending confirmation");

    // Verify booking was created with correct data
    expect(prisma.bookings.create).toHaveBeenCalledWith({
      data: expect.objectContaining({
        userId: "user-1",
        customerName: "John Doe",
        customerPhone: "+1234567890",
        service: "Dental Checkup",
        appointmentTime: "10:00",
        status: "pending",
        source: "phone_call",
        conversationId: "conv-456",
      }),
    });
  });

  it("should use caller_number if patient_phone is not provided", async () => {
    (prisma.users.findFirst as jest.Mock).mockResolvedValue({
      id: "user-1",
    });

    (prisma.bookings.create as jest.Mock).mockResolvedValue({
      id: "booking-123",
      userId: "user-1",
      customerName: "John Doe",
      customerPhone: "+9876543210",
      customerEmail: null,
      service: "Checkup",
      appointmentDate: new Date("2024-01-20T14:00:00Z"),
      appointmentTime: "14:00",
      duration: 30,
      staffMember: null,
      depositAmount: null,
      depositPaid: false,
      totalAmount: 0,
      status: "pending",
      source: "phone_call",
      notes: null,
    });

    const request = createRequest({
      date: "2024-01-20",
      time: "14:00",
      service: "Checkup",
      patient_name: "John Doe",
      caller_number: "+9876543210",
      agent_id: "agent-123",
    });

    const response = await POST(request);

    expect(response.status).toBe(200);

    expect(prisma.bookings.create).toHaveBeenCalledWith({
      data: expect.objectContaining({
        customerPhone: "+9876543210",
      }),
    });
  });
});
