import { useCallback } from 'react';
import { usePersSDK } from '../providers/PersSDKProvider';
import type { BookingDTO, CreateBookingDTO, UpdateBookingDTO } from '@explorins/pers-shared';
import type { BookingQueryOptions, BookingValidationOptions } from '@explorins/pers-sdk';

// Re-export for consumers
export type { BookingQueryOptions, BookingValidationOptions } from '@explorins/pers-sdk';

/**
 * Hook interface for booking operations
 */
export interface BookingHook {
  /** Get all bookings with optional filters */
  getBookings: (options?: BookingQueryOptions) => Promise<BookingDTO[]>;
  /** Get a single booking by ID */
  getBookingById: (id: string) => Promise<BookingDTO>;
  /** Create a new booking */
  createBooking: (data: CreateBookingDTO) => Promise<BookingDTO>;
  /** Update an existing booking */
  updateBooking: (id: string, data: UpdateBookingDTO) => Promise<BookingDTO>;
  /** Delete a booking */
  deleteBooking: (id: string) => Promise<void>;
  /** Check if a user has a valid booking */
  hasValidBooking: (userId: string, options?: BookingValidationOptions) => Promise<boolean>;
  /** Whether the SDK is initialized */
  isInitialized: boolean;
  /** Whether the user is authenticated */
  isAuthenticated: boolean;
}

/**
 * React hook for booking management operations
 * 
 * Provides methods to create, read, update, and delete bookings,
 * as well as checking if a user has a valid booking for redemption eligibility.
 * 
 * @example
 * ```typescript
 * import { useBookings } from '@explorins/pers-sdk-react-native';
 * 
 * function BookingScreen() {
 *   const { getBookings, createBooking, hasValidBooking } = useBookings();
 *   
 *   // List all bookings for a user
 *   const userBookings = await getBookings({ userId: 'user-123' });
 *   
 *   // Create a booking
 *   const newBooking = await createBooking({
 *     userId: 'user-123',
 *     locationName: 'Resort Hotel',
 *     checkInDate: '2026-06-01',
 *     checkOutDate: '2026-06-05'
 *   });
 *   
 *   // Check if user has valid booking for redemption
 *   const isEligible = await hasValidBooking('user-123', { status: 'active' });
 * }
 * ```
 */
export const useBookings = (): BookingHook => {
  const { sdk, isInitialized, isAuthenticated } = usePersSDK();

  /**
   * Get all bookings with optional filters
   * 
   * @param options - Query options including userId, businessId, status filters
   * @returns Array of booking DTOs
   */
  const getBookings = useCallback(async (options?: BookingQueryOptions): Promise<BookingDTO[]> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      return await sdk.bookings.getAll(options);
    } catch (error) {
      console.error('Failed to fetch bookings:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  /**
   * Get a single booking by ID
   * 
   * @param id - Booking UUID
   * @returns Booking DTO
   */
  const getBookingById = useCallback(async (id: string): Promise<BookingDTO> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      return await sdk.bookings.getById(id);
    } catch (error) {
      console.error('Failed to fetch booking:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  /**
   * Create a new booking
   * 
   * @param data - Booking data including userId, locationName, dates
   * @returns Created booking DTO
   */
  const createBooking = useCallback(async (data: CreateBookingDTO): Promise<BookingDTO> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      return await sdk.bookings.create(data);
    } catch (error) {
      console.error('Failed to create booking:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  /**
   * Update an existing booking
   * 
   * @param id - Booking UUID
   * @param data - Partial booking data to update
   * @returns Updated booking DTO
   */
  const updateBooking = useCallback(async (id: string, data: UpdateBookingDTO): Promise<BookingDTO> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      return await sdk.bookings.update(id, data);
    } catch (error) {
      console.error('Failed to update booking:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  /**
   * Delete a booking
   * 
   * @param id - Booking UUID
   */
  const deleteBooking = useCallback(async (id: string): Promise<void> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      await sdk.bookings.delete(id);
    } catch (error) {
      console.error('Failed to delete booking:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  /**
   * Check if a user has a valid booking
   * 
   * @param userId - User ID to check
   * @param options - Validation options including status filter
   * @returns true if user has valid booking matching criteria
   */
  const hasValidBooking = useCallback(async (
    userId: string, 
    options?: BookingValidationOptions
  ): Promise<boolean> => {
    if (!isInitialized || !sdk) {
      throw new Error('SDK not initialized. Call initialize() first.');
    }
    
    try {
      return await sdk.bookings.hasValidBooking(userId, options);
    } catch (error) {
      console.error('Failed to check booking validity:', error);
      throw error;
    }
  }, [sdk, isInitialized]);

  return {
    getBookings,
    getBookingById,
    createBooking,
    updateBooking,
    deleteBooking,
    hasValidBooking,
    isInitialized,
    isAuthenticated,
  };
};
