import apiFetch from './apiFetch';

export const getMusicians = page => {
  return new Promise((resolve, reject) => {
    apiFetch(`/search/musicians?results=true`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

// export const getPeople = (page) => {
//   return new Promise((resolve, reject) => {
//     apiFetch(`/filter?page=${page}`)
//     .then(response => resolve(response))
//     .catch(error => reject(error))
//   })
// }

export const getPersonById = id => {
  return new Promise((resolve, reject) =>
    apiFetch(`/users/${id}/profile`)
      .then(response => resolve(response))
      .catch(error => reject(error))
  );
};

export const getUserDetail = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) =>
    apiFetch(`/users/${id}?${new URLSearchParams(rest)}`)
      .then(response => resolve(response))
      .catch(error => reject(error))
  );
};

export const getPeople = ({ data, offset, limit } = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/filter?offset=${offset}&limit=${limit}`, {
      method: 'POST',
      body: JSON.stringify(data)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getPeopleByIds = ({ userId, ids }) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/filter_by_ids`, {
      method: 'POST',
      body: JSON.stringify({ user_ids: ids })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getPeopleIndex = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getLobbyUsers = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/lobby`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const updateUser = (id, data) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${id}`, {
      method: 'POST',
      body: JSON.stringify(data)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getGenres = () => {
  return new Promise((resolve, reject) => {
    apiFetch('/genres')
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getInstruments = () => {
  return new Promise((resolve, reject) => {
    apiFetch('/instruments')
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getCurrentUser = () => {
  return new Promise((resolve, reject) => {
    apiFetch('/me')
      .then(response => resolve(response))
      .catch(error => reject(error))
  })
}

export const getFriends = userId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/friends`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const addFriend = (userId, friendId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/friend_requests`, {
      method: 'POST',
      body: JSON.stringify({ friend_id: friendId })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const removeFriend = (userId, friendId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/friends/${friendId}`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getTextMessages = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/text_messages?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const createTextMessage = options => {
  return new Promise((resolve, reject) => {
    apiFetch(`/text_messages`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const createLobbyChatMessage = options => {
  return new Promise((resolve, reject) => {
    apiFetch(`/chat`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getNotifications = (userId, options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/my_notifications?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const readNotifications = (userId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/my_notifications/read`, {
      method: 'POST'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const acceptFriendRequest = (userId, options = {}) => {
  return new Promise((resolve, reject) => {
    const { status, friend_request_id } = options;
    apiFetch(`/users/${userId}/friend_requests/${friend_request_id}`, {
      method: 'POST',
      body: JSON.stringify({ status })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const deleteNotification = (userId, notificationId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/notifications/${notificationId}`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getSessions = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getSession = sessionId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${sessionId}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

// Fetch session history, optionally including pending entries
export const getSessionHistory = (id, includePending = false) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${id}/history?includePending=${includePending}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const joinSession = (options = {}) => {
  const { session_id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${session_id}/participants`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const leaveSession = clientId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/participants/${clientId}`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getFriendsSessions = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/friends`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getPublicSessions = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/public`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getInactiveSessions = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/inactive`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getSessionsHistory = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/history?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const createSession = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch('/sessions', {
      method: 'post',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error))
  })
}

export const getLatencyToUsers = (currentUserId, participantIds) => {
  return new Promise((resolve, reject) => {
    const query = participantIds.map(id => `user_ids[]=${id}`).join('&');
    apiFetch(`/users/${currentUserId}/latencies?${query}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getLobbyChatMessages = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/chat?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getCountries = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/countries`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getRegions = countryId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/regions?country=${countryId}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getCities = (countryId, regionId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/cities?country=${countryId}&region=${regionId}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const postUpdateAccountEmail = (userId, options) => {
  const { email, current_password } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/update_email_alt`, {
      method: 'POST',
      body: JSON.stringify({ update_email: email, current_password })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const postUpdateAccountPassword = (userId, options) => {
  const { new_password, current_password } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/set_password`, {
      method: 'POST',
      body: JSON.stringify({ old_password: current_password, new_password, new_password_confirm: new_password })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const requestPasswordReset = userId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/request_reset_password`, {
      method: 'POST'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const resetPassword = email => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/reset_password`, {
      method: 'POST',
      body: JSON.stringify({ email })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const requstResetForgotPassword = email => {
  return new Promise((resolve, reject) => {
    apiFetch(`/request_reset_forgot_password`, {
      method: 'POST',
      body: JSON.stringify({ email })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const resetForgotPassword = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/reset_forgot_password`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const postUserAppInteraction = (userId, options) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/app_interactions`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getSubscription = () => {
  return new Promise((resolve, reject) => {
    apiFetch('/recurly/get_subscription')
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const changeSubscription = plan_code => {
  const options = { plan_code };
  return new Promise((resolve, reject) => {
    apiFetch('/recurly/change_subscription', {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getInvoiceHistory = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/invoice_history?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const createAffiliatePartner = options => {
  return new Promise((resolve, reject) => {
    apiFetch('/affiliate_partners', {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getAffiliatePartnerData = userId => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/affiliate_partner`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getAffiliateSignups = (options = {}) => {
  if (!options.per_page) {
    options.per_page = 10;
  }
  if (!options.page) {
    options.page = 0;
  }
  return new Promise((resolve, reject) => {
    apiFetch(`/affiliate_partners/signups?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getAffiliatePayments = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/affiliate_partners/payments`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const postAffiliatePartnerData = (userId, params) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/affiliate_partner`, {
      method: 'POST',
      body: JSON.stringify(params)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const autocompleteJamTracks = (input, limit) => {
  const query = { match: input, limit };
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/autocomplete?${new URLSearchParams(query)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getPurchasedJamTracks = (options = {}) => {
  options = { ...options, show_purchased_only: true };
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/purchased?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getJamTrackArtists = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/artists?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getJamTracks = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks?${new URLSearchParams(options)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getJamTrack = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/${id}?${new URLSearchParams(rest)}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getJamTrackPublic = options => {
  const { plan_code } = options;
  return new Promise((resolve, reject) => {
    // This does not make sense; historical reasons here
    apiFetch(`/jamtracks/band/${plan_code}?${new URLSearchParams({ plan_code })}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getJamTrackBySlug = options => {
  const { slug } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/${slug}`, {
      baseUrl: process.env.REACT_APP_CLIENT_BASE_URL
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const addJamtrackToShoppingCart = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/shopping_carts/add_jamtrack`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getAppFeatures = (env) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/app_features?env=${env}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const getShoppingCart = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/shopping_carts`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const removeShoppingCart = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/shopping_carts`, {
      method: 'DELETE',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getBillingInfo = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/billing_info`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const updateBillingInfo = (options = {}) => {
  const params = { billing_info: options };
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/update_billing_info`, {
      method: 'PUT',
      body: JSON.stringify(params)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const createRecurlyAccount = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/create_account`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const placeOrder = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/place_order`, {
      method: 'POST'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const postUserEvent = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/event/record`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const userOpenedJamTrackWebPlayer = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/progression/opened_jamtrack_web_player`, {
      method: 'POST'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const markMixdownActive = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/jamtracks/${id}/mixdowns/active`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const createMixdown = options => {
  return new Promise((resolve, reject) => {
    apiFetch(`/mixdowns`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const enqueueMixdown = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/mixdowns/${id}/enqueue`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const deleteMixdown = id => {
  return new Promise((resolve, reject) => {
    apiFetch(`/mixdowns/${id}`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const updateAvatar = options => {
  const { id, ...rest } = options;
  const opts = {
    url: rest['url'],
    // crop_selection: rest['crop_selection']
  };
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${id}/avatar_v2`, {
      method: 'POST',
      body: JSON.stringify(opts)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const deleteAvatar = id => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${id}/avatar_v2`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const createAlert = (subject, data) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/alerts`, {
      method: 'POST',
      body: JSON.stringify({ subject, data })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const getClientDownloads = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/artifacts/clients`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

// Recording-related functions
export const startRecording = (options) => {
  return new Promise((resolve, reject) => {
    apiFetch('/recordings/start', {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => response.json())
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
};

export const stopRecording = (options) => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/recordings/${id}/stop`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => response.json())
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
};

export const getRecordingPromise = (options) => {
  const { id } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/recordings/${id}`)
      .then(response => response.json())
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
};
export const getObsPluginDownloads = () => {
  return new Promise((resolve, reject) => {
    apiFetch(`/artifacts/OBSPlugin`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

//paypalPlaceOrder
export const paypalPlaceOrder = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/paypal/checkout/confirm`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};


export const submitStripe = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/stripe`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  })
}

// function updatePayment(options) {
//   options = options || {}
//   return $.ajax({
//     type: "POST",
//     url: '/api/recurly/update_payment',
//     dataType: "json",
//     contentType: 'application/json',
//     data: JSON.stringify(options)
//   })
// }

export const updatePayment = (options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/recurly/update_payment`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const updateEmail = (userId, email, current_password) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${userId}/update_email`, {
      method: 'POST',
      body: JSON.stringify({ update_email: email, current_password })
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const updateUdpReachable = (options = {}) => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/users/${id}/udp_reachable`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const deleteParticipant = (clientId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/participants/${clientId}`, {
      method: 'DELETE'
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const createDiagnostic = (options = {}) => {
  let data = null;
  try {
    data = JSON.stringify(options);
  } catch (e) {
    data = JSON.stringify({ data_error: "unable to JSON.stringify debug data:" + e.toString() });
  }
  return new Promise((resolve, reject) => {
    apiFetch(`/diagnostics`, {
      method: 'POST',
      body: data
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const putTrackSyncChange = (options = {}) => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${id}/tracks`, {
      method: 'PUT',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const updateSessionSettings = (options = {}) => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${id}`, {
      method: 'PUT',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const submitSessionFeedback = (clientId, options = {}) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/participant_histories/${clientId}/rating`, {
      method: 'POST',
      body: JSON.stringify(options)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const getVideoConferencingRoomUrl = (musicSessionId) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/video/room/${musicSessionId}`, {
      baseUrl: process.env.REACT_APP_CLIENT_BASE_URL
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export const closeJamTrack = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${id}/jam_tracks/close`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

export const openMetronome = options => {
  const { id, ...rest } = options;
  return new Promise((resolve, reject) => {
    apiFetch(`/sessions/${id}/metronome/open`, {
      method: 'POST',
      body: JSON.stringify(rest)
    })
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};

/**
 * Fetch chat messages for a channel
 * @param {Object} params - Request parameters
 * @param {string} params.channel - Channel type ('session', 'global', 'lesson')
 * @param {string} [params.sessionId] - Session ID (required for session channel)
 * @param {number} [params.before] - Pagination cursor
 * @returns {Promise<{messages: Array, next: number|null}>} Message list with pagination
 */
export const getChatMessages = async ({ channel, sessionId, before }) => {
  const params = new URLSearchParams({ channel });
  // Backend expects 'music_session' not 'session_id'
  if (sessionId) params.append('music_session', sessionId);
  if (before !== undefined) params.append('before', before);

  const baseUrl = process.env.REACT_APP_API_BASE_URL;
  const response = await fetch(`${baseUrl}/chat?${params}`, {
    method: 'GET',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' }
  });

  if (!response.ok) {
    throw new Error(`${response.status} ${response.statusText}`);
  }

  return response.json();
};

/**
 * Send a chat message to a channel
 * @param {Object} params - Request parameters
 * @param {string} params.channel - Channel type ('session', 'global', 'lesson')
 * @param {string} [params.sessionId] - Session ID (required for session channel)
 * @param {string} params.message - Message content
 * @param {string} [params.clientId] - Client ID (used by backend to exclude sender from WebSocket broadcast)
 * @returns {Promise<{message: Object}>} Created message object
 */
export const sendChatMessage = async ({ channel, sessionId, message, clientId }) => {
  const body = { channel, message };
  if (sessionId) body.music_session = sessionId;
  if (clientId) body.client_id = clientId;

  const baseUrl = process.env.REACT_APP_API_BASE_URL;
  const response = await fetch(`${baseUrl}/chat`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });

  if (!response.ok) {
    const error = await response.json().catch(() => ({}));
    throw new Error(error.error || `${response.status} ${response.statusText}`);
  }

  return response.json();
};

/**
 * Upload file attachment to S3 via backend
 *
 * IMPORTANT: Uses native fetch, NOT apiFetch wrapper
 * Reason: FormData requires browser to set Content-Type with boundary
 *
 * @param {FormData} formData - FormData with files[], session_id, attachment_type
 * @returns {Promise<Object[]>} Array of uploaded file metadata
 */
export const uploadMusicNotation = (formData) => {
  const baseUrl = process.env.REACT_APP_API_BASE_URL || 'http://www.jamkazam.local:3000';

  return new Promise((resolve, reject) => {
    fetch(`${baseUrl}/music_notations`, {
      method: 'POST',
      credentials: 'include', // Include session cookie
      // Do NOT set Content-Type - browser sets it with boundary for FormData
      body: formData
    })
      .then(response => {
        if (!response.ok) {
          // Pass status to error for specific handling
          const error = new Error('Upload failed');
          error.status = response.status;
          throw error;
        }
        return response.json();
      })
      .then(data => resolve(data))
      .catch(error => reject(error));
  });
};

/**
 * Get signed S3 URL for attachment download
 *
 * Uses apiFetch because response is JSON (not FormData)
 *
 * @param {string} id - MusicNotation UUID
 * @returns {Promise<Object>} { url: "https://s3..." }
 */
export const getMusicNotationUrl = (id) => {
  return new Promise((resolve, reject) => {
    apiFetch(`/music_notations/${id}`)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
};
