
export type PartnerReportFrequency = "weekly" | "monthly" | "yearly";
export type PartnerReportSchedule = {
  id: string;
  label: string;
  enabled: boolean;
  frequency: PartnerReportFrequency;
  periodDays: number;
  recipientWhatsapp: string;
  nextRunAt: string;
  lastRunAt?: string;
  lastStatus?: string;
  includeAllListings?: boolean;
  listingIds?: string[];
  createdAt: string;
  updatedAt: string;
};
export type PartnerReportDeliveryLog = {
  id: string;
  createdAt: string;
  channel: "whatsapp";
  recipientWhatsapp: string;
  periodDays: number;
  status: "sent" | "not-configured" | "failed" | "generated";
  message: string;
  scheduleId?: string;
  providerMessageId?: string;
};

export type SupplierCategory = "supplies" | "food" | "activities" | "help" | "accommodation" | "cleaning" | "gardening" | "maintenance" | "pool-service" | "electrical" | "plumbing" | "security" | "property-management" | "visitor-services" | "traveller-services";
export type SupplierPackage = "basic" | "featured" | "premium" | "sponsor";
export type SupplierStatus = "draft" | "pending" | "live" | "paused" | "archived";
export type SupplierBillingCycle = "free-basic" | "monthly" | "once-off-launch" | "lead-fee" | "sponsor";
export type SupplierBillingStatus = "not-set" | "not-invoiced" | "awaiting-payment" | "trial" | "paid" | "overdue" | "comped" | "cancelled";

export type AccommodationTier = "standard" | "featured" | "top-featured" | "partner";
export type AccommodationStatus = "draft" | "active" | "paused" | "expired" | "archived";
export type AccommodationMonthlyFeeStatus = "not-set" | "not-invoiced" | "awaiting-payment" | "trial" | "paid" | "overdue" | "comped" | "cancelled";
export type AccommodationBillingCycle = "free-basic" | "once-off-launch" | "monthly" | "annual" | "lead-fee" | "commission";
export type AccommodationEnquiryRouting = "mpc" | "contact" | "both";
export type AccommodationImage = { id: string; url: string; alt: string; caption: string; sortOrder: number; };

export type ListingClaimStatus = "new" | "reviewing" | "published" | "rejected" | "linked-to-contact-pipeline";
export type ListingClaimRequest = {
  id: string;
  createdAt: string;
  updatedAt: string;
  listingId?: string;
  listingSlug?: string;
  listingName: string;
  claimType: "contact" | "manager" | "agent" | "business-contact" | "other";
  requesterName: string;
  requesterEmail: string;
  requesterWhatsapp: string;
  proofSummary: string;
  requestedChanges?: string;
  packageInterest?: "basic" | "featured" | "top-featured" | "premium" | "not-sure";
  status: ListingClaimStatus;
  adminNotes?: string;
  linkedProspectId?: string;
  linkedAccommodationId?: string;
  reviewedAt?: string;
  history?: { at: string; action: string; note?: string }[];
};


export type ListingRequestRequest = ListingClaimRequest;
export type AccommodationListing = {
  id: string;
  name: string;
  slug: string;
  tagline: string;
  locationLabel: string;
  description: string;
  shortDescription: string;
  tier: AccommodationTier;
  status: AccommodationStatus;
  monthlyFeeStatus: AccommodationMonthlyFeeStatus;
  featured: boolean;
  partnerBadge: boolean;
  ownerName: string;
  ownerEmail: string;
  ownerPhone: string;
  ownerWhatsapp: string;
  enquiryRecipientEmail: string;
  enquiryRouting: AccommodationEnquiryRouting;
  whatsappNumber: string;
  phoneNumber: string;
  email: string;
  websiteUrl: string;
  externalBookingUrl?: string;
  externalBookingLabel?: string;
  mapUrl: string;
  latitude?: string;
  longitude?: string;
  sleeps: number;
  bedrooms: number;
  bathrooms: number;
  priceFromLabel: string;
  amenities: string[];
  bestFor: string[];
  houseRules: string[];
  images: AccommodationImage[];
  sortOrder: number;
  createdAt: string;
  updatedAt: string;
  internalNotes: string;
  billingCycle?: AccommodationBillingCycle;
  launchPackagePrice?: number;
  setupFeeAmount?: number;
  listingStartDate?: string;
  nextRenewalDate?: string;
  paymentReference?: string;
  paymentNotes?: string;
  autoExpireDate?: string;
  packageName?: string;
  packageDescription?: string;
  packageStartDate?: string;
  packageExpiryDate?: string;
  homepageEligible?: boolean;
  categoryTags?: string[];
  searchKeywords?: string[];
  minimumImagesRequired?: number;
  ownerReportNotes?: string;
  contactReportNotes?: string;
  contactReportEmailEnabled?: boolean;
  lastContactReportAt?: string;
  contactName?: string;
  contactEmail?: string;
  contactPhone?: string;
  contactWhatsapp?: string;
  featuredLeadFeeAmount?: number;
  lastOwnerReportAt?: string;
  ownerReportEmailEnabled?: boolean;
  verifiedLeadFeeAmount?: number;
  leadFeeStatus?: AccommodationMonthlyFeeStatus;
  lastMinuteBoostPrice?: number;
  lastMinuteBoostStartDate?: string;
  lastMinuteBoostEndDate?: string;
  founderLaunchMonths?: number;
  performanceModelEnabled?: boolean;
  commissionPercent?: number;
  revenueNotes?: string;
};

export type Supplier = {
  id: string; name: string; slug: string; category: SupplierCategory; subcategory: string;
  package: SupplierPackage; status: SupplierStatus; mpcCode: string; description: string;
  serviceArea: string; services: string[]; openLabel: string; deliveryLabel?: string;
  paymentOptions: string; whatsappNumber: string; phoneNumber: string; email?: string;
  websiteUrl?: string; bookingUrl?: string; seoTitle?: string; seoDescription?: string;
  mapUrl: string; imageSrc: string; imageAlt?: string; lastVerified: string; supplierResponsibilityAccepted: boolean; sortOrder: number;
  contactName?: string; contactEmail?: string; contactWhatsapp?: string; billingCycle?: SupplierBillingCycle; billingStatus?: SupplierBillingStatus; packageName?: string; packagePrice?: number; setupFeeAmount?: number; sponsorPackageName?: string; sponsorStartDate?: string; sponsorEndDate?: string; nextRenewalDate?: string; paymentReference?: string; paymentNotes?: string; verifiedLeadFeeAmount?: number; featuredLeadFeeAmount?: number; leadFeeStatus?: SupplierBillingStatus; homepageSponsorEligible?: boolean; lastFeatured?: string; categorySponsorEligible?: boolean; lastMinuteBoostPrice?: number; lastMinuteBoostStartDate?: string; lastMinuteBoostEndDate?: string; internalNotes?: string;
};
export type ImageSlotCrop = { desktopX?: number; desktopY?: number; mobileX?: number; mobileY?: number; };
export type ImageSlot = { key: string; label: string; description: string; url: string; fallbackUrl: string; alt: string; updatedAt: string; crop?: ImageSlotCrop; };
export type SiteSettings = {
  siteName: string;
  tagline: string;
  siteUrl: string;
  partnerEmail: string;
  whatsappNumber: string;
  footerDisclaimer: string;
  footerDisrequester?: string;
  facebookUrl?: string;
  instagramUrl?: string;
  safariAssistantEnabled?: boolean;
  safariAssistantLabel?: string;
  safariAssistantMessage?: string;
  checkoutMode?: "manual" | "woocommerce";
  shopBaseUrl?: string;
  wooProductPathPrefix?: string;
};
export type EnquiryRouting = "mpc" | "contact" | "both";
export type LeadStatus = "new" | "contacted" | "waiting-for-visitor" | "quoted" | "booked" | "not-available" | "closed";
export type LeadPriority = "normal" | "high" | "urgent";
export type Integrations = {
  leadWebhookEnabled: boolean;
  leadWebhookUrl: string;
  supplierOnboardingWebhookEnabled: boolean;
  supplierOnboardingWebhookUrl: string;
  webhookSecret: string;
  notificationEmail?: string;
  stayEnquiryRecipientEmail?: string;
  stayEnquiryRouting?: EnquiryRouting;
  sendVisitorConfirmations?: boolean;
  guideDeliveryEnabled?: boolean;
  guideDeliveryReplyToEmail?: string;
  lastEmailStatus?: string;
  lastLeadWebhookStatus?: string;
  lastSupplierWebhookStatus?: string;
};
export type GateInfo = { id: string; gateName: string; month: string; openTime: string; closeTime: string; sourceUrl: string; notes: string; lastVerified: string; active: boolean; };
export type EmergencyContact = { id: string; name: string; category: string; phoneNumber: string; whatsappNumber?: string; location?: string; description: string; availability: string; lastVerified: string; active: boolean; sortOrder: number; };
export type LegalPage = { slug: string; title: string; body: string; version: string; lastUpdated: string; published: boolean; };
export type ContentBlock = { key: string; label: string; value: string; updatedAt: string; };
export type FeatureFlag = { key: string; label: string; description: string; category: string; enabled: boolean; updatedAt: string; };
export type LaunchChecklistStatus = "blocked" | "todo" | "in-progress" | "ready" | "featured";
export type LaunchChecklistItem = { key: string; label: string; description: string; category: string; status: LaunchChecklistStatus; blocking: boolean; notes: string; updatedAt: string; };

export type ProductKind = "route-pack" | "guide" | "printable" | "bundle" | "sample" | "planning-help";
export type ProductAccess = "free" | "paid" | "bundle";
export type AdminProduct = { id: string; slug: string; title: string; kind: ProductKind; access: ProductAccess; normalPrice: number; prelaunchPrice: number; priceLabel: string; normalPriceLabel?: string; prelaunchOnly?: boolean; badge: string; description: string; active: boolean; featured?: boolean; orderHref: string; sampleHref?: string; previewHref?: string; privateFile?: string; publicFile?: string; sortOrder: number; imageSrc?: string; coverSrc?: string; };
export type DownloadAccessProduct = { productId: string; status: "pending" | "available" | "delivered"; unlockedAt?: string; deliveredAt?: string; notes?: string; };
export type DownloadAccess = { id: string; accessToken: string; customerName: string; customerEmail: string; customerWhatsapp: string; products: DownloadAccessProduct[]; status: "pending" | "paid" | "delivered" | "paused"; paymentReference?: string; internalNotes?: string; createdAt: string; updatedAt: string; expiresAt?: string; };


export type PrelaunchProspectStage =
  | "prospect"
  | "visited"
  | "interested"
  | "needs-follow-up"
  | "agreement-sent"
  | "payment-requested"
  | "paid"
  | "listing-setup"
  | "live"
  | "not-interested";

export type PrelaunchProspectType =
  | "accommodation"
  | "local-business"
  | "professional-service"
  | "sponsorship"
  | "other";

export type PrelaunchProspectPriority = "low" | "normal" | "high" | "urgent";

export type PrelaunchProspect = {
  id: string;
  createdAt: string;
  updatedAt: string;
  prospectType: PrelaunchProspectType;
  name: string;
  contactName: string;
  contactEmail: string;
  contactWhatsapp: string;
  stage: PrelaunchProspectStage;
  priority: PrelaunchProspectPriority;
  tierDiscussed: string;
  priceDiscussed: string;
  founderSlot: boolean;
  nextFollowUpAt?: string;
  followUpNote?: string;
  linkedPartnerId?: string;
  linkedAccommodationId?: string;
  notes?: string;
  history?: { at: string; action: string; note?: string }[];
};

export type PrelaunchSettings = {
  founderRoundLabel: string;
  founderTarget: number;
  founderReserveTarget?: number;
  founderAccommodationReserve: number;
  founderBusinessReserve: number;
  founderFlexibleReserve: number;
  founderUsedManual: number;
  founderPublicCounterEnabled?: boolean;
  founderPublicMode?: "safe" | "first-round" | "remaining";
  founderPublicLabel?: string;
  launchCampaignDate?: string;
  notes?: string;
  updatedAt: string;
};


export type SalesDeskOrderStatus = "new" | "payment-requested" | "awaiting-proof" | "proof-received" | "payment-featured" | "paid" | "delivered" | "cancelled" | "refunded" | "issue";
export type SalesDeskOrder = {
  id: string;
  createdAt: string;
  updatedAt: string;
  sourceLeadId?: string;
  orderCode: string;
  customerName: string;
  customerEmail: string;
  customerWhatsapp: string;
  productId: string;
  productTitle: string;
  amount: number;
  currency: "ZAR";
  status: SalesDeskOrderStatus;
  paymentMethod: "manual" | "payfast-link" | "eft" | "cash" | "other";
  paymentReference?: string;
  paymentRequestedAt?: string;
  proofReceivedAt?: string;
  paymentVerifiedAt?: string;
  paidAt?: string;
  deliveredAt?: string;
  followUpAt?: string;
  deliveryAccessId?: string;
  deliveryAccessToken?: string;
  internalNotes?: string;
  customerNotes?: string;
  adminHistory?: { at: string; action: string; note?: string }[];
};

export type PartnerBillingStatus = "draft" | "payment-requested" | "active-paid" | "trial" | "overdue" | "paused" | "cancelled" | "comped";
export type PartnerBillingCycle = "monthly" | "annual" | "once-off" | "free";
export type PartnerBillingType = "accommodation" | "local-business" | "professional-service" | "sponsorship" | "other";
export type PartnerBillingRecord = {
  id: string;
  createdAt: string;
  updatedAt: string;
  partnerType: PartnerBillingType;
  partnerId?: string;
  partnerName: string;
  contactName: string;
  contactEmail: string;
  contactWhatsapp: string;
  packageName: string;
  tierLabel: string;
  billingCycle: PartnerBillingCycle;
  agreedAmount: number;
  currency: "ZAR";
  founderRate: boolean;
  status: PartnerBillingStatus;
  startDate?: string;
  nextRenewalDate?: string;
  lastPaymentAt?: string;
  paymentReference?: string;
  invoiceNotes?: string;
  internalNotes?: string;
  relatedListingStatus?: string;
  adminHistory?: { at: string; action: string; note?: string }[];
};

export type EmailNurtureKind = "free-guide" | "stay" | "route-pack" | "accommodation-help" | "business-onboarding" | "listing-onboarding";
export type EmailNurtureStepKey = "day1" | "day3" | "day7";
export type EmailNurtureStep = { key: EmailNurtureStepKey; scheduledFor: string; sentAt?: string; attempts?: number; lastStatus?: string; };
export type EmailNurtureState = {
  kind: EmailNurtureKind;
  enabled: boolean;
  createdAt: string;
  updatedAt?: string;
  steps: Record<EmailNurtureStepKey, EmailNurtureStep>;
};

export type AnalyticsEventType =
  | "page_view"
  | "cta_click"
  | "pdf_open"
  | "file_download"
  | "bundle_view"
  | "bundle_order_click"
  | "free_pack_download_click"
  | "local_option_click"
  | "business_contact_click"
  | "business_directions_click"
  | "accommodation_view"
  | "accommodation_contact_click"
  | "form_submit"
  | string;

export type AnalyticsEvent = {
  id: string;
  eventType: AnalyticsEventType;
  createdAt: string;
  page: string;
  path?: string;
  label?: string;
  target?: string;
  source?: string | null;
  referrer?: string | null;
  utmSource?: string | null;
  utmMedium?: string | null;
  utmCampaign?: string | null;
  utmContent?: string | null;
  utmTerm?: string | null;
  productId?: string | null;
  supplierId?: string | null;
  supplierName?: string | null;
  accommodationId?: string | null;
  accommodationName?: string | null;
  sessionId?: string | null;
  userAgent?: string | null;
  metadata?: Record<string, unknown> | null;
};

export type LeadEvent = {
  id: string;
  receivedAt: string;
  updatedAt?: string;
  status?: LeadStatus;
  priority?: LeadPriority;
  adminNotes?: string;
  followUpAt?: string;
  followUpNote?: string;
  assignedTo?: string;
  crmUpdatedAt?: string;
  crmHistory?: { at: string; action: string; status?: LeadStatus; priority?: LeadPriority; note?: string }[];
  convertedValue?: number;
  lostReason?: string;
  supplierId?: string;
  supplierName?: string;
  category?: string;
  buttonType?: "email" | "map" | "website" | "booking-link" | "accommodation-enquiry" | "listing-view" | "featured-impression" | "contact-report" | string;
  leadCode?: string;
  page?: string;
  source?: string | null;
  campaign?: string | null;
  userAgent?: string;
  contactName?: string;
  contactValue?: string;
  travelMonth?: string;
  stayingAt?: string;
  accommodationId?: string;
  accommodationSlug?: string;
  accommodationName?: string;
  consentAccepted?: boolean;
  marketingConsent?: boolean;
  marketingChannels?: string[];
  marketingTopics?: string[];
  doNotContact?: boolean;
  doNotContactAt?: string;
  dayPlan?: { input: any; routeSlug: string; addOnSupplierIds?: string[] };
  routePackId?: string;
  routePackTitle?: string;
  guideSlug?: string;
  guideTitle?: string;
  guideDownloadUrl?: string;
  selectedBundleSlug?: string;
  selectedBundleTitle?: string;
  visitorType?: string;
  routeInterest?: string;
  familyStatus?: string;
  accommodationIntent?: string;
  localHelpInterest?: string;
  sourcePage?: string;
  gatedDeliveryCode?: string;
  gatedDeliveryCodeExpiresAt?: string;
  gatedDeliveryCodeUsedAt?: string;
  gatedDeliveryAccessToken?: string;
  gatedDeliveryAccessExpiresAt?: string;
  gatedDeliveryAccessUsedAt?: string;
  gatedDeliveryDownloadUrl?: string;
  freeGuideCode?: string;
  freeGuideCodeExpiresAt?: string;
  freeGuideCodeUsedAt?: string;
  freeGuideAccessToken?: string;
  freeGuideAccessExpiresAt?: string;
  freeGuideAccessUsedAt?: string;
  emailStatus?: string;
  confirmationStatus?: string;
  nurture?: EmailNurtureState;
  nurtureStatus?: string;
  lastNurtureStatus?: string;
  calculatorScore?: number;
  urgencyScore?: number;
  planningRiskScore?: number;
  revenuePotentialScore?: number;
  intentClassification?: string;
  recommendedProduct?: string;
  adminActionPlan?: string;
};

export type HomepageHeroMedia = {
  mode: "image" | "video";
  videoUrl: string;
  posterSlotKey: string;
  originalFilename?: string;
  mimeType?: "video/mp4";
  fileSizeBytes?: number;
  updatedAt: string;
};
export type AdminState = {
  version: number;
  updatedAt: string;
  siteSettings: SiteSettings;
  integrations: Integrations;
  imageSlots: ImageSlot[];
  homepageHeroMedia: HomepageHeroMedia;
  suppliers: Supplier[];
  accommodationListings: AccommodationListing[];
  gateInfo: GateInfo[];
  emergencyContacts: EmergencyContact[];
  legalPages: LegalPage[];
  contentBlocks: ContentBlock[];
  featureFlags: FeatureFlag[];
  launchChecklist: LaunchChecklistItem[];
  productCatalogue: AdminProduct[];
  downloadAccess: DownloadAccess[];
  salesDeskOrders: SalesDeskOrder[];
  partnerBillingRecords: PartnerBillingRecord[];
  prelaunchProspects: PrelaunchProspect[];
  prelaunchSettings: PrelaunchSettings;
  leadEvents: LeadEvent[];
  analyticsEvents: AnalyticsEvent[];
  partnerReportSchedules: PartnerReportSchedule[];
  partnerReportDeliveryLog: PartnerReportDeliveryLog[];
  listingClaimRequests: ListingClaimRequest[];
};
