/**
 * Data Mapping Utilities for Demo Bookings
 *
 * This module handles data transformation between different naming conventions:
 * - Database: snake_case
 * - Frontend (React): camelCase
 * - API Requests: camelCase
 * - API Responses: camelCase
 *
 * These mappers ensure consistent data formats across the application while
 * respecting each layer's conventions.
 *
 * @module lib/staff-dashboard/demo-bookings/mappers
 */

import type {
  DemoBookingRecord,
  DemoBooking,
  DemoBookingUpdate,
  DemoBookingUpdateRequest,
} from './types';

/**
 * Map database record (snake_case) to frontend format (camelCase)
 *
 * Converts a database record to the format expected by the frontend.
 * This mapping is necessary because:
 * - Database uses snake_case convention
 * - JavaScript/TypeScript uses camelCase convention
 *
 * @param record - Database record (snake_case)
 * @returns Frontend-friendly object (camelCase)
 *
 * @example
 * const dbRecord = { full_name: "John", appointment_date: "..." };
 * const frontendData = mapBookingToFrontend(dbRecord);
 * console.log(frontendData.fullName); // "John"
 */
export function mapBookingToFrontend(record: DemoBookingRecord): DemoBooking {
  return {
    id: record.id,
    fullName: record.full_name,
    email: record.email,
    telephone: record.telephone,
    appointmentDate: record.appointment_date,
    appointmentTime: record.appointment_time,
    duration: record.duration,
    specialRequirements: record.special_requirements,
    language: record.language,
    status: record.status,
    webhookStatus: record.webhook_status,
    webhookRetryCount: record.webhook_retry_count,
    webhookLastAttempt: record.webhook_last_attempt,
    webhookResponse: record.webhook_response,
    meetingLink: record.meeting_link,
    internalNotes: record.internal_notes,
    contactedAt: record.contacted_at,
    contactedBy: record.contacted_by,
    createdAt: record.created_at,
    updatedAt: record.updated_at,
  };
}

/**
 * Map multiple database records to frontend format
 *
 * Convenience function for mapping arrays of records.
 *
 * @param records - Array of database records
 * @returns Array of frontend-friendly objects
 *
 * @example
 * const dbRecords = [...]; // from database query
 * const frontendBookings = mapBookingsToFrontend(dbRecords);
 */
export function mapBookingsToFrontend(records: DemoBookingRecord[]): DemoBooking[] {
  return records.map(mapBookingToFrontend);
}

/**
 * Map frontend update request (camelCase) to database format (snake_case)
 *
 * Converts an API request body to the database format.
 * Automatically adds updated_at timestamp.
 *
 * @param request - Update request from frontend (camelCase)
 * @param staffUserId - ID of staff user making the update
 * @returns Database update object (snake_case)
 *
 * @example
 * const request = { status: "confirmed", meetingLink: "https://..." };
 * const dbUpdate = mapUpdateRequestToDatabase(request, "staff-123");
 * // Returns: { status: "confirmed", meeting_link: "https://...", contacted_by: "staff-123", ... }
 */
export function mapUpdateRequestToDatabase(
  request: Omit<DemoBookingUpdateRequest, 'bookingId'>,
  staffUserId: string
): DemoBookingUpdate {
  const updateData: DemoBookingUpdate = {
    updated_at: new Date().toISOString(),
  };

  // Map status update
  if (request.status) {
    updateData.status = request.status;

    // Auto-set contacted fields when confirming
    if (request.status === 'confirmed') {
      updateData.contacted_at = new Date().toISOString();
      updateData.contacted_by = staffUserId;
    }
  }

  // Map meeting link
  if (request.meetingLink !== undefined) {
    updateData.meeting_link = request.meetingLink;

    // Auto-set contacted fields when adding meeting link
    if (request.meetingLink) {
      updateData.contacted_at = new Date().toISOString();
      updateData.contacted_by = staffUserId;
    }
  }

  // Map internal notes
  if (request.internalNotes !== undefined) {
    updateData.internal_notes = request.internalNotes;
  }

  return updateData;
}

/**
 * Map frontend filters to Supabase query parameters
 *
 * This is used internally by the query builder but exported for testing.
 *
 * @param filters - Filter object from frontend
 * @returns Object with filter parameters for database query
 *
 * @internal
 */
export function mapFiltersToQueryParams(filters: {
  status?: string;
  search?: string;
  dateRange?: string;
}) {
  return {
    status: filters.status !== 'all' ? filters.status : undefined,
    search: filters.search || undefined,
    dateRange: filters.dateRange !== 'all' ? filters.dateRange : undefined,
  };
}

/**
 * Create date range boundary for filtering
 *
 * Calculates the start date for a given date range filter.
 *
 * @param range - Date range type (today, week, month)
 * @returns ISO string of the start date, or null if range is 'all'
 *
 * @example
 * const startDate = getDateRangeBoundary('week');
 * // Returns ISO string for 7 days ago
 */
export function getDateRangeBoundary(
  range: 'all' | 'today' | 'week' | 'month'
): string | null {
  if (range === 'all') return null;

  const now = new Date();
  const start = new Date();

  switch (range) {
    case 'today':
      start.setHours(0, 0, 0, 0);
      break;
    case 'week':
      start.setDate(now.getDate() - 7);
      break;
    case 'month':
      start.setMonth(now.getMonth() - 1);
      break;
  }

  return start.toISOString();
}

/**
 * Map frontend date to database timestamp
 *
 * Ensures dates are properly formatted as ISO strings.
 *
 * @param date - Date object or ISO string
 * @returns ISO string timestamp
 */
export function mapDateToTimestamp(date: Date | string): string {
  if (typeof date === 'string') {
    return new Date(date).toISOString();
  }
  return date.toISOString();
}

/**
 * Sanitize search query for search operations
 *
 * Prevents injection and formats search term for queries.
 *
 * @param search - Raw search term from user
 * @returns Sanitized search term
 *
 * @example
 * const safe = sanitizeSearchTerm("John's Company");
 * // Returns: "John's Company" (with proper escaping)
 */
export function sanitizeSearchTerm(search: string): string {
  // Remove potential SQL injection characters
  // Allow letters, numbers, spaces, @, ., -, _, and Arabic characters
  return search.replace(/[^\w\s@.\-_\u0600-\u06FF]/g, '');
}

/**
 * Build search pattern for database ILIKE
 *
 * Formats search term with wildcards for partial matching.
 *
 * @param search - Search term
 * @returns Pattern for ILIKE query (e.g., "%john%")
 */
export function buildSearchPattern(search: string): string {
  const sanitized = sanitizeSearchTerm(search);
  return `%${sanitized}%`;
}
