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

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

export const propertyTypeValidator = v.union(
  v.literal("APARTMENT"),
  v.literal("VILLA"),
  v.literal("TOWNHOUSE"),
  v.literal("PENTHOUSE"),
  v.literal("DUPLEX"),
  v.literal("STUDIO"),
  v.literal("COMPOUND_VILLA"),
  v.literal("OFFICE"),
  v.literal("RETAIL"),
  v.literal("WAREHOUSE"),
  v.literal("SHOWROOM"),
  v.literal("LAND_RESIDENTIAL"),
  v.literal("LAND_COMMERCIAL"),
  v.literal("HOTEL_APARTMENT"),
  v.literal("SERVICED_APARTMENT"),
);

export const propertyStatusValidator = v.union(
  v.literal("COMING_SOON"),
  v.literal("AVAILABLE"),
  v.literal("UNDER_OFFER"),
  v.literal("SOLD"),
  v.literal("RENTED"),
  v.literal("OFF_MARKET"),
  v.literal("EXPIRED"),
);

export const listingTypeValidator = v.union(
  v.literal("SALE"),
  v.literal("RENT"),
);

export const furnishingTypeValidator = v.union(
  v.literal("FURNISHED"),
  v.literal("SEMI_FURNISHED"),
  v.literal("UNFURNISHED"),
);

export const ownershipTypeValidator = v.union(
  v.literal("FREEHOLD"),
  v.literal("LEASEHOLD"),
);

export const viewingTypeValidator = v.union(
  v.literal("INDIVIDUAL"),
  v.literal("TOUR"),
  v.literal("OPEN_HOUSE"),
  v.literal("VIRTUAL"),
  v.literal("SECOND_VIEWING"),
  v.literal("DEVELOPER_VISIT"),
  v.literal("AREA_TOUR"),
);

export const viewingStatusValidator = v.union(
  v.literal("REQUESTED"),
  v.literal("CONFIRMED"),
  v.literal("IN_PROGRESS"),
  v.literal("VIEW_COMPLETED"),
  v.literal("CANCELLED"),
  v.literal("NO_SHOW"),
  v.literal("RESCHEDULED"),
);

export const transactionStageValidator = v.union(
  v.literal("INQUIRY"),
  v.literal("QUALIFIED"),
  v.literal("VIEWING_SCHEDULED"),
  v.literal("VIEWING_COMPLETED"),
  v.literal("INTERESTED"),
  v.literal("OFFER_MADE"),
  v.literal("NEGOTIATION"),
  v.literal("OFFER_ACCEPTED"),
  v.literal("DEPOSIT_PAID"),
  v.literal("CONTRACT_SIGNED"),
  v.literal("PAYMENT_PROCESSING"),
  v.literal("TX_COMPLETED"),
  v.literal("LOST"),
);

export const gccCurrencyCodeValidator = v.union(
  v.literal("QAR"),
  v.literal("SAR"),
  v.literal("AED"),
  v.literal("KWD"),
  v.literal("BHD"),
  v.literal("OMR"),
);

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

export const realEstateTables = {
  property: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    titleEn: v.string(),
    titleAr: v.optional(v.string()),
    descriptionEn: v.optional(v.string()),
    descriptionAr: v.optional(v.string()),
    referenceNumber: v.optional(v.string()),
    propertyType: propertyTypeValidator,
    listingType: listingTypeValidator,
    status: propertyStatusValidator,
    furnishing: furnishingTypeValidator,
    ownership: ownershipTypeValidator,
    isOffPlan: v.boolean(),
    handoverDate: v.optional(v.number()),
    bedrooms: v.optional(v.number()),
    bathrooms: v.optional(v.number()),
    builtUpArea: v.optional(v.number()),
    plotArea: v.optional(v.number()),
    floor: v.optional(v.number()),
    totalFloors: v.optional(v.number()),
    parkingSpaces: v.optional(v.number()),
    yearBuilt: v.optional(v.number()),
    country: v.string(),
    city: v.string(),
    district: v.optional(v.string()),
    // Free-form street address line (e.g. "123 Al Waab Street, Near Aspire Zone").
    // Complements the structured district/building/unit fields with a
    // human-readable address the WhatsApp AI agent surfaces to customers.
    streetAddress: v.optional(v.string()),
    buildingName: v.optional(v.string()),
    unitNumber: v.optional(v.string()),
    latitude: v.optional(v.number()),
    longitude: v.optional(v.number()),
    mapUrl: v.optional(v.string()),
    price: v.number(),
    currency: gccCurrencyCodeValidator,
    pricePerSqm: v.optional(v.number()),
    isNegotiable: v.boolean(),
    serviceCharges: v.optional(v.number()),
    minContractMonths: v.optional(v.number()),
    paymentTerms: v.optional(v.string()),
    amenities: v.any(),
    highlights: v.any(),
    keyLocation: v.optional(v.string()),
    accessNotes: v.optional(v.string()),
    viewingHoursNote: v.optional(v.string()),
    listingBrokerId: v.optional(v.string()),
    viewCount: v.number(),
    inquiryCount: v.number(),
    viewingCount: v.number(),
    listedAt: v.number(),
    soldRentedAt: v.optional(v.number()),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_status", ["userId", "status"])
    .index("by_organizationId_status", ["organizationId", "status"])
    .index("by_country_city_district", ["country", "city", "district"])
    .index("by_propertyType_listingType", ["propertyType", "listingType"])
    .index("by_price", ["price"])
    .index("by_bedrooms", ["bedrooms"])
    .index("by_status_listedAt", ["status", "listedAt"])
    .index("by_referenceNumber", ["referenceNumber"]),

  property_image: defineTable({
    prismaId: v.optional(v.string()),
    propertyId: v.string(),
    url: v.string(),
    caption: v.optional(v.string()),
    captionAr: v.optional(v.string()),
    type: v.string(),
    sortOrder: v.number(),
    isPrimary: v.boolean(),
    createdAt: v.number(),
  }).index("by_propertyId_sortOrder", ["propertyId", "sortOrder"]),

  broker: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    nameEn: v.string(),
    nameAr: v.optional(v.string()),
    phone: v.string(),
    email: v.optional(v.string()),
    whatsappNumber: v.optional(v.string()),
    photoUrl: v.optional(v.string()),
    bioEn: v.optional(v.string()),
    bioAr: v.optional(v.string()),
    licenseNumber: v.optional(v.string()),
    languages: v.any(),
    areaSpecializations: v.any(),
    typeSpecializations: v.any(),
    workingDays: v.any(),
    workStartTime: v.string(),
    workEndTime: v.string(),
    maxViewingsPerDay: v.number(),
    isActive: v.boolean(),
    totalViewings: v.number(),
    totalClosings: v.number(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_isActive", ["userId", "isActive"])
    .index("by_organizationId_isActive", ["organizationId", "isActive"]),

  broker_availability: defineTable({
    prismaId: v.optional(v.string()),
    brokerId: v.string(),
    date: v.number(),
    startTime: v.string(),
    endTime: v.string(),
    isBlocked: v.boolean(),
    reason: v.optional(v.string()),
    createdAt: v.number(),
  }).index("by_brokerId_date", ["brokerId", "date"]),

  property_viewing: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    // Optional so the WhatsApp AI agent can book a general viewing
    // request (e.g. "2BR in The Pearl, Saturday 3pm") before the
    // broker has matched a specific listing. Broker assigns later
    // via the dashboard.
    propertyId: v.optional(v.string()),
    brokerId: v.optional(v.string()),
    tourId: v.optional(v.string()),
    clientName: v.string(),
    clientPhone: v.string(),
    clientEmail: v.optional(v.string()),
    viewingType: viewingTypeValidator,
    viewingDate: v.number(),
    viewingTime: v.string(),
    duration: v.number(),
    status: viewingStatusValidator,
    meetingLink: v.optional(v.string()),
    clientTimezone: v.optional(v.string()),
    maxAttendees: v.optional(v.number()),
    currentAttendees: v.number(),
    accessConfirmed: v.boolean(),
    keyCollected: v.boolean(),
    interestLevel: v.optional(v.string()),
    clientNotes: v.optional(v.string()),
    confirmationSentAt: v.optional(v.number()),
    reminder24hSentAt: v.optional(v.number()),
    reminder2hSentAt: v.optional(v.number()),
    followUpSentAt: v.optional(v.number()),
    source: v.string(),
    conversationId: v.optional(v.string()),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_viewingDate", ["userId", "viewingDate"])
    .index("by_organizationId_viewingDate", ["organizationId", "viewingDate"])
    .index("by_brokerId_viewingDate", ["brokerId", "viewingDate"])
    .index("by_propertyId_viewingDate", ["propertyId", "viewingDate"])
    .index("by_status", ["status"])
    .index("by_tourId", ["tourId"]),

  viewing_tour: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    brokerId: v.optional(v.string()),
    clientName: v.string(),
    clientPhone: v.string(),
    tourDate: v.number(),
    startTime: v.string(),
    estimatedEnd: v.optional(v.string()),
    notes: v.optional(v.string()),
    status: v.string(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_tourDate", ["userId", "tourDate"])
    .index("by_brokerId_tourDate", ["brokerId", "tourDate"]),

  viewing_feedback: defineTable({
    prismaId: v.optional(v.string()),
    viewingId: v.string(),
    overallRating: v.optional(v.number()),
    priceOpinion: v.optional(v.string()),
    sizeOpinion: v.optional(v.string()),
    locationOpinion: v.optional(v.string()),
    conditionNote: v.optional(v.string()),
    wouldRecommend: v.optional(v.boolean()),
    brokerNotes: v.optional(v.string()),
    interestLevel: v.optional(v.string()),
    suggestedAction: v.optional(v.string()),
    createdAt: v.number(),
  }).index("by_viewingId", ["viewingId"]),

  client_requirements: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    customerId: v.optional(v.string()),
    clientName: v.string(),
    clientPhone: v.string(),
    clientEmail: v.optional(v.string()),
    listingType: v.optional(listingTypeValidator),
    propertyTypes: v.any(),
    minBedrooms: v.optional(v.number()),
    maxBedrooms: v.optional(v.number()),
    minBudget: v.optional(v.number()),
    maxBudget: v.optional(v.number()),
    currency: gccCurrencyCodeValidator,
    preferredAreas: v.any(),
    minArea: v.optional(v.number()),
    mustHaves: v.any(),
    dealBreakers: v.any(),
    timeline: v.optional(v.string()),
    purpose: v.optional(v.string()),
    financingType: v.optional(v.string()),
    preApproved: v.boolean(),
    leadScore: v.number(),
    lastContactAt: v.optional(v.number()),
    isActive: v.boolean(),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_isActive", ["userId", "isActive"])
    .index("by_organizationId_isActive", ["organizationId", "isActive"])
    .index("by_leadScore", ["leadScore"]),

  property_match: defineTable({
    prismaId: v.optional(v.string()),
    propertyId: v.string(),
    requirementId: v.string(),
    matchScore: v.number(),
    matchReasons: v.any(),
    status: v.string(),
    sentAt: v.optional(v.number()),
    createdAt: v.number(),
  })
    .index("by_requirementId_matchScore", ["requirementId", "matchScore"])
    .index("by_status", ["status"])
    .index("by_propertyId_requirementId", ["propertyId", "requirementId"]),

  tenant_issue: defineTable({
    userId: v.string(),
    organizationId: v.optional(v.string()),
    propertyId: v.string(),
    title: v.string(),
    description: v.optional(v.string()),
    category: v.union(
      v.literal("plumbing"),
      v.literal("electrical"),
      v.literal("hvac"),
      v.literal("structural"),
      v.literal("appliance"),
      v.literal("pest_control"),
      v.literal("cleaning"),
      v.literal("other"),
    ),
    priority: v.union(
      v.literal("low"),
      v.literal("medium"),
      v.literal("high"),
      v.literal("urgent"),
    ),
    status: v.union(
      v.literal("open"),
      v.literal("in_progress"),
      v.literal("resolved"),
      v.literal("closed"),
    ),
    unit: v.optional(v.string()),
    tenantName: v.optional(v.string()),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_status", ["userId", "status"])
    .index("by_propertyId_status", ["propertyId", "status"])
    .index("by_priority", ["priority"]),

  real_estate_transaction: defineTable({
    prismaId: v.optional(v.string()),
    userId: v.string(),
    organizationId: v.optional(v.string()),
    propertyId: v.string(),
    clientName: v.string(),
    clientPhone: v.string(),
    clientEmail: v.optional(v.string()),
    brokerId: v.optional(v.string()),
    stage: transactionStageValidator,
    offerAmount: v.optional(v.number()),
    counterAmount: v.optional(v.number()),
    agreedAmount: v.optional(v.number()),
    currency: gccCurrencyCodeValidator,
    depositAmount: v.optional(v.number()),
    depositPaid: v.boolean(),
    depositPaidAt: v.optional(v.number()),
    depositPaymentId: v.optional(v.string()),
    offerDate: v.optional(v.number()),
    contractDate: v.optional(v.number()),
    completionDate: v.optional(v.number()),
    handoverDate: v.optional(v.number()),
    notes: v.optional(v.string()),
    lostReason: v.optional(v.string()),
    createdAt: v.number(),
    updatedAt: v.number(),
  })
    .index("by_userId_stage", ["userId", "stage"])
    .index("by_organizationId_stage", ["organizationId", "stage"])
    .index("by_propertyId", ["propertyId"]),
};
