import apiClient from '../../../shared/services/apiClient';

export interface BookingData {
  room_id: number;
  check_in_date: string; 
  check_out_date: string; 
  guest_count: number;
  notes?: string;
  payment_method: 'cash' | 'stripe' | 'paypal';
  total_price: number;
  guest_info: {
    full_name: string;
    email: string;
    phone: string;
  };
  services?: Array<{
    service_id: number;
    quantity: number;
  }>;
  promotion_code?: string;
  referral_code?: string;
}

export interface Booking {
  id: number;
  booking_number: string;
  user_id: number;
  room_id: number;
  check_in_date: string;
  check_out_date: string;
  guest_count: number;
  total_price: number;
  original_price?: number;
  discount_amount?: number;
  promotion_code?: string;
  status: 
    | 'pending' 
    | 'confirmed' 
    | 'cancelled' 
    | 'checked_in' 
    | 'checked_out';
  payment_method: 'cash' | 'stripe' | 'paypal';
  payment_status: 
    | 'unpaid' 
    | 'paid' 
    | 'refunded';
  deposit_paid?: boolean;
  requires_deposit?: boolean;
  notes?: string;
  guest_info?: {
    full_name: string;
    email: string;
    phone: string;
  };
  room?: {
    id: number;
    room_number: string;
    floor: number;
    status: string;
    room_type: {
      id: number;
      name: string;
      base_price: number;
      capacity: number;
      images?: string[];
    };
  };
  user?: {
    id: number;
    name: string;
    full_name: string;
    email: string;
    phone?: string;
    phone_number?: string;
  };
  payments?: Payment[];
  payment_balance?: {
    total_paid: number;
    total_price: number;
    remaining_balance: number;
    is_fully_paid: boolean;
    payment_percentage: number;
  };
  createdAt: string;
  updatedAt: string;
}

export interface Payment {
  id: number;
  booking_id: number;
  amount: number;
  payment_method: string;
  payment_type: 'full' | 'deposit' | 'remaining';
  deposit_percentage?: number;
  payment_status: 'pending' | 'completed' | 'failed' | 'refunded';
  transaction_id?: string;
  payment_date?: string;
  notes?: string;
  created_at: string;
  updated_at: string;
}

export interface BookingResponse {
  success: boolean;
  data: {
    booking: Booking;
  };
  message?: string;
}

export interface BookingsResponse {
  success: boolean;
  status?: string;
  data: {
    bookings: Booking[];
    pagination?: {
      page: number;
      limit: number;
      total: number;
      totalPages: number;
    };
  };
  message?: string;
}

export interface CheckBookingResponse {
  success: boolean;
  data: {
    booking: Booking;
  };
  message?: string;
}

export const createBooking = async (
  bookingData: BookingData
): Promise<BookingResponse> => {
  const response = await apiClient.post<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(
    '/bookings',
    bookingData
  );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!data.data?.booking) {
    throw new Error('Booking not found');
  }
  return {
    success: data.status === 'success' || data.success === true,
    data: { booking: data.data.booking },
    message: data.message,
  };
};

export const getMyBookings = async (): 
  Promise<BookingsResponse> => {
  const response = await apiClient.get<{ status?: string; success?: boolean; data?: { bookings?: Booking[]; pagination?: { page: number; limit: number; total: number; totalPages: number } }; message?: string }>(
    '/bookings/me'
  );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  return {
    success: data.status === 'success' || data.success === true,
    data: {
      bookings: data.data?.bookings || [],
      pagination: data.data?.pagination,
    },
    message: data.message,
  };
};

export const getBookingById = async (
  id: number
): Promise<BookingResponse> => {
  const response = await apiClient.get<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(
    `/bookings/${id}`
  );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!data.data?.booking) {
    throw new Error('Booking not found');
  }
  return {
    success: data.status === 'success' || data.success === true,
    data: { booking: data.data.booking },
    message: data.message,
  };
};

export const cancelBooking = async (
  id: number
): Promise<BookingResponse> => {
  const response = await apiClient.patch<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(
    `/bookings/${id}/cancel`
  );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!data.data?.booking) {
    throw new Error('Booking not found');
  }
  return {
    success: data.status === 'success' || data.success === true,
    data: { booking: data.data.booking },
    message: data.message,
  };
};

export const checkBookingByNumber = async (
  bookingNumber: string
): Promise<CheckBookingResponse> => {
  const response = 
    await apiClient.get<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(
      `/bookings/check/${bookingNumber}`
    );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!data.data?.booking) {
    throw new Error('Booking not found');
  }
  return {
    success: data.status === 'success' || data.success === true,
    data: { booking: data.data.booking },
    message: data.message,
  };
};

export const getAllBookings = async (
  params?: {
    status?: string;
    search?: string;
    page?: number;
    limit?: number;
    startDate?: string;
    endDate?: string;
  }
): Promise<BookingsResponse> => {
  const response = await apiClient.get<{ status?: string; success?: boolean; data?: { bookings?: Booking[]; pagination?: { page: number; limit: number; total: number; totalPages: number } }; message?: string }>('/bookings', { params });
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  return {
    success: data.status === 'success' || data.success === true,
    data: {
      bookings: data.data?.bookings || [],
      pagination: data.data?.pagination,
    },
    message: data.message,
  };
};

export const updateBooking = async (
  id: number,
  data: Partial<Booking>
): Promise<BookingResponse> => {
  const response = await apiClient.put<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(`/bookings/${id}`, data);
  const responseData = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!responseData.data?.booking) {
    throw new Error('Booking update failed');
  }
  return {
    success: responseData.status === 'success' || responseData.success === true,
    data: { booking: responseData.data.booking },
    message: responseData.message,
  };
};

export const checkRoomAvailability = async (
  roomId: number,
  checkInDate: string,
  checkOutDate: string
): Promise<{ available: boolean; message?: string }> => {
  try {
    const response = await apiClient.get(
      '/rooms/available',
      {
        params: {
          roomId,
          from: checkInDate,
          to: checkOutDate,
        },
      }
    );
    
    
    if (response.data?.data?.available !== undefined) {
      return {
        available: response.data.data.available,
        message: response.data.data.message,
      };
    }
    
    
    return {
      available: true,
      message: response.data?.message || 'Room is available',
    };
  } catch (error: unknown) {
    // Type guard for API errors
    const isApiError = (e: unknown): e is { response?: { status?: number; data?: { message?: string; detail?: string } } } => {
      return typeof e === 'object' && e !== null;
    };
    
    if (isApiError(error) && (error.response?.status === 409 || error.response?.status === 404)) {
      return {
        available: false,
        message: 
          error.response.data?.message || 
          error.response.data?.detail ||
          'Room already booked during this time',
      };
    }
    throw error;
  }
};

export const notifyPayment = async (
  bookingId: number,
  file?: File
): Promise<{ success: boolean; message?: string }> => {
  const formData = new FormData();
  formData.append('bookingId', bookingId.toString());
  
  if (file) {
    formData.append('receipt', file);
  }

  
  const response = await apiClient.post(
    '/notify/payment',
    formData
  );
  
  return response.data;
};

export const generateQRCode = (
  bookingNumber: string,
  amount: number,
  bankCode?: string,
  accountNumber?: string,
  accountName?: string
): string => {
  // If bank details are not provided, return empty string (QR code won't be generated)
  if (!bankCode || !accountNumber || !accountName) {
    return '';
  }
  
  const transferContent = bookingNumber;
  
  // Generate QR code URL (using generic QR code service, not Vietnam-specific)
  // Note: This is a placeholder - you may want to use a different QR code service
  // that supports international bank transfers
  const qrUrl = 
    `https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=` +
    encodeURIComponent(`Bank: ${bankCode}, Account: ${accountNumber}, Name: ${accountName}, Amount: ${amount}, Reference: ${transferContent}`);
  
  return qrUrl;
};

export const adminCreateBooking = async (
  bookingData: BookingData & { user_id: number; status?: string }
): Promise<BookingResponse> => {
  const response = await apiClient.post<{ status?: string; success?: boolean; data?: { booking?: Booking }; message?: string }>(
    '/bookings/admin-create',
    bookingData
  );
  const data = response.data;
  // Handle both 'status: success' and 'success: true' formats
  if (!data.data?.booking) {
    throw new Error('Booking not found');
  }
  return {
    success: data.status === 'success' || data.success === true,
    data: { booking: data.data.booking },
    message: data.message,
  };
};

export default {
  createBooking,
  getMyBookings,
  getBookingById,
  cancelBooking,
  checkBookingByNumber,
  checkRoomAvailability,
  notifyPayment,
  generateQRCode,
  getAllBookings,
  updateBooking,
  adminCreateBooking,
};
