import { defineTable } from "convex/server";
import { v } from "convex/values";

// ── Enums ──────────────────────────────────────────────────────────────

export const bookingStatusValidator = v.union(
  v.literal("pending"),
  v.literal("confirmed"),
  v.literal("cancelled"),
  v.literal("completed"),
  v.literal("no_show"),
);

export const bookingSourceValidator = v.union(
  v.literal("whatsapp"),
  v.literal("manual"),
  v.literal("demo_booking"),
  v.literal("widget"),
  v.literal("phone_call"),
  v.literal("walk_in"),
);

export const webhookStatusValidator = v.union(
  v.literal("pending"),
  v.literal("sent"),
  v.literal("failed"),
);

export const reminderStatusValidator = v.union(
  v.literal("pending"),
  v.literal("sent"),
  v.literal("partial"),
  v.literal("failed"),
  v.literal("skipped"),
);

export const noteTypeValidator = v.union(
  v.literal("DEMO_BOOKING"),
  v.literal("CONTACT"),
  v.literal("USER"),
  v.literal("GENERAL"),
);

// ── Tables ─────────────────────────────────────────────────────────────

export const bookingTables = {
  bookings: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    customerName: v.string(),
    customerPhone: v.string(),
    customerEmail: v.optional(v.string()),
    service: v.string(),
    appointmentDate: v.number(),
    appointmentTime: v.string(),
    duration: v.number(),
    staffMember: v.optional(v.string()),
    depositAmount: v.optional(v.number()),
    depositPaid: v.boolean(),
    depositPaidAt: v.optional(v.number()),
    depositPaymentId: v.optional(v.string()),
    depositReminderSentAt: v.optional(v.number()),
    depositReminderCount: v.number(),
    totalAmount: v.number(),
    sectorMetadata: v.optional(v.any()),
    itemType: v.optional(v.string()),
    status: bookingStatusValidator,
    source: bookingSourceValidator,
    conversationId: v.optional(v.string()),
    notes: v.optional(v.string()),
    // Cancellation + refund tracking (booking-refund.service.ts)
    cancelledAt: v.optional(v.number()),
    cancelledVia: v.optional(v.string()), // 'whatsapp' | 'staff' | 'customer_web'
    refundStatus: v.optional(v.string()), // 'succeeded' | 'failed' | 'not_eligible' | 'not_applicable' | 'pending'
    refundId: v.optional(v.string()), // Stripe refund.id
    refundAmount: v.optional(v.number()), // major units (QAR)
    refundedAt: v.optional(v.number()),
    refundError: v.optional(v.string()),
    // 24-hour WhatsApp reminder tracking (appointment-reminder.service.ts)
    reminderSentAt: v.optional(v.number()),
    reminderStatus: v.optional(reminderStatusValidator),
    reminderError: v.optional(v.string()),
    reminderChannel: v.optional(v.string()), // 'whatsapp' | 'sms' | ...
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_appointmentDate", ["appointmentDate"])
    .index("by_conversationId", ["conversationId"])
    .index("by_depositPaid", ["depositPaid"])
    .index("by_status", ["status"])
    .index("by_userId", ["userId"])
    .index("by_userId_status", ["userId", "status"])
    .index("by_userId_appointmentDate", ["userId", "appointmentDate"])
    .index("by_userId_createdAt", ["userId", "createdAt"])
    .index("by_userId_status_appointmentDate", [
      "userId",
      "status",
      "appointmentDate",
    ])
    .index("by_status_appointmentDate", ["status", "appointmentDate"])
    .index("by_organizationId", ["organizationId"])
    .index("by_organizationId_status", ["organizationId", "status"])
    .index("by_organizationId_appointmentDate", [
      "organizationId",
      "appointmentDate",
    ])
    .index("by_reminderStatus_appointmentDate", [
      "reminderStatus",
      "appointmentDate",
    ]),

  booking_notes: defineTable({
    prismaId: v.optional(v.string()),
    bookingId: v.string(),
    authorId: v.string(),
    authorName: v.string(),
    content: v.string(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_authorId", ["authorId"])
    .index("by_bookingId", ["bookingId"])
    .index("by_createdAt", ["createdAt"]),

  demo_bookings: defineTable({
    prismaId: v.optional(v.string()),
    fullName: v.string(),
    email: v.string(),
    telephone: v.string(),
    appointmentDate: v.number(),
    appointmentTime: v.string(),
    duration: v.string(),
    specialRequirements: v.optional(v.string()),
    language: v.string(),
    status: bookingStatusValidator,
    webhookStatus: webhookStatusValidator,
    webhookRetryCount: v.number(),
    webhookLastAttempt: v.optional(v.number()),
    webhookResponse: v.optional(v.string()),
    createdAt: v.number(),
    updatedAt: v.number(),
    assignedTo: v.optional(v.string()),
    contactedAt: v.optional(v.number()),
    contactedBy: v.optional(v.string()),
    customerTimezone: v.optional(v.string()),
    googleCalendarEventId: v.optional(v.string()),
    googleConferenceId: v.optional(v.string()),
    googleJoinUrl: v.optional(v.string()),
    internalNotes: v.optional(v.string()),
    meetingLink: v.optional(v.string()),
    reminderEmailSent: v.boolean(),
    reminderError: v.optional(v.string()),
    reminderSentAt: v.optional(v.number()),
    reminderStatus: v.optional(reminderStatusValidator),
    reminderWhatsAppSent: v.boolean(),
  })
    .index("by_appointmentDate", ["appointmentDate"])
    .index("by_assignedTo", ["assignedTo"])
    .index("by_createdAt", ["createdAt"])
    .index("by_customerTimezone", ["customerTimezone"])
    .index("by_email", ["email"])
    .index("by_googleCalendarEventId", ["googleCalendarEventId"])
    .index("by_prismaId", ["prismaId"])
    .index("by_reminderStatus_appointmentDate", [
      "reminderStatus",
      "appointmentDate",
    ])
    .index("by_status", ["status"])
    .index("by_webhookStatus", ["webhookStatus"]),

  staff_notes: defineTable({
    prismaId: v.optional(v.string()),
    staffId: v.string(),
    noteType: noteTypeValidator,
    referenceId: v.string(),
    note: v.string(),
    isInternal: v.boolean(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_createdAt", ["createdAt"])
    .index("by_noteType", ["noteType"])
    .index("by_referenceId", ["referenceId"])
    .index("by_staffId", ["staffId"]),

  company_availability: defineTable({
    prismaId: v.optional(v.string()),
    organizationId: v.string(),
    dayOfWeek: v.number(),
    startTime: v.string(),
    endTime: v.string(),
    slotDuration: v.number(),
    bufferTime: v.number(),
    isActive: v.boolean(),
    timezone: v.string(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_organizationId", ["organizationId"])
    .index("by_organizationId_dayOfWeek_isActive", [
      "organizationId",
      "dayOfWeek",
      "isActive",
    ])
    .index("by_isActive", ["isActive"]),

  appointment_types: defineTable({
    prismaId: v.optional(v.string()),
    organizationId: v.string(),
    nameEn: v.string(),
    nameAr: v.string(),
    duration: v.number(),
    price: v.optional(v.number()),
    category: v.optional(v.string()),
    categoryAr: v.optional(v.string()),
    itemType: v.optional(v.string()),
    isActive: v.boolean(),
    sortOrder: v.number(),
    createdAt: v.number(),
    updatedAt: v.number(),
    createdBy: v.optional(v.string()),
  })
    .index("by_organizationId", ["organizationId"])
    .index("by_organizationId_isActive", ["organizationId", "isActive"])
    .index("by_organizationId_category", ["organizationId", "category"])
    .index("by_sortOrder", ["sortOrder"]),

  waitlists: defineTable({
    prismaId: v.optional(v.string()),
    title: v.string(),
    titleAr: v.optional(v.string()),
    description: v.optional(v.string()),
    descriptionAr: v.optional(v.string()),
    category: v.string(),
    isActive: v.boolean(),
    isPublic: v.boolean(),
    userId: v.optional(v.string()),
    createdBy: v.string(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_category", ["category"])
    .index("by_createdAt", ["createdAt"])
    .index("by_isActive", ["isActive"])
    .index("by_isPublic", ["isPublic"])
    .index("by_userId", ["userId"]),

  waitlist_signups: defineTable({
    prismaId: v.optional(v.string()),
    waitlistId: v.string(),
    userId: v.optional(v.string()),
    name: v.string(),
    email: v.string(),
    mobile: v.string(),
    notes: v.optional(v.string()),
    addedBy: v.optional(v.string()),
    createdAt: v.number(),
  })
    .index("by_createdAt", ["createdAt"])
    .index("by_email", ["email"])
    .index("by_waitlistId", ["waitlistId"]),
};
