/**
 * Track Sync Service
 *
 * Handles synchronization of track configuration to server via PUT /api/sessions/{id}/tracks
 *
 * @module services/trackSyncService
 */

import { putTrackSyncChange } from '../helpers/rest';
import { getInstrumentServerIdFromClientId } from '../helpers/globals';

/**
 * Builds track sync payload from Redux state
 *
 * @param {Object} state - Redux state
 * @param {string} sessionId - Session ID
 * @param {string} clientId - Client ID
 * @returns {Object} Track sync payload for API
 */
export const buildTrackSyncPayload = (state, sessionId, clientId) => {
  const { userTracks = [], backingTracks = [], metronome } = state.activeSession;

  // Build user tracks for API
  const tracks = userTracks.map(track => ({
    client_track_id: track.id,
    client_resource_id: track.rid,
    instrument_id: getInstrumentServerIdFromClientId(track.instrument_id),
    sound: track.stereo ? 'stereo' : 'mono'
  }));

  // Build backing tracks for API
  const backingTracksForAPI = backingTracks.map(bt => ({
    client_track_id: bt.id,
    client_resource_id: bt.rid,
    filename: bt.filename
  }));

  return {
    client_id: clientId,
    tracks,
    backing_tracks: backingTracksForAPI,
    metronome_open: metronome?.isOpen || false
  };
};

/**
 * Syncs tracks to server
 *
 * Redux thunk action that:
 * 1. Validates prerequisites (clientId, sessionId, sessionJoined)
 * 2. Builds payload from Redux state
 * 3. Calls PUT /api/sessions/{id}/tracks API
 * 4. Dispatches Redux actions on success
 * 5. Handles errors gracefully
 *
 * @param {string} sessionId - Session ID to sync tracks for
 * @param {string} clientId - Client ID from server context
 * @returns {Function} Redux thunk
 */
export const syncTracksToServer = (sessionId, clientId) => async (dispatch, getState) => {
  const state = getState();
  const { hasJoined } = state.activeSession;

  // Guard: Check clientId exists
  if (!clientId) {
    console.warn('[Track Sync] Skipped: Client ID not available');
    return { skipped: true, reason: 'no_client_id' };
  }

  // Guard: Check sessionId exists
  if (!sessionId) {
    console.warn('[Track Sync] Skipped: No session ID');
    return { skipped: true, reason: 'no_session_id' };
  }

  // Guard: Check session joined
  if (!hasJoined) {
    console.warn('[Track Sync] Skipped: Session not joined');
    return { skipped: true, reason: 'session_not_joined' };
  }

  // Build payload
  const payload = buildTrackSyncPayload(state, sessionId, clientId);

  try {
    console.log('[Track Sync] Syncing tracks to server:', {
      sessionId,
      trackCount: payload.tracks.length,
      backingTrackCount: payload.backing_tracks.length,
      metronomeOpen: payload.metronome_open
    });

    // Call API
    const response = await putTrackSyncChange({ id: sessionId, ...payload });

    console.log('[Track Sync] Success:', response.tracks?.length || 0, 'tracks synced');

    // Dispatch Redux actions to update state
    // TODO: Import actual action creators from activeSessionSlice
    if (response.tracks) {
      dispatch({ type: 'activeSession/setUserTracks', payload: response.tracks });
    }
    if (response.backing_tracks) {
      dispatch({ type: 'activeSession/setBackingTrackData', payload: response.backing_tracks });
    }

    return { success: true, response };

  } catch (error) {
    console.error('[Track Sync] Failed:', error);

    // TODO: Dispatch error action
    // dispatch(showError('Failed to sync tracks'));

    return { success: false, error };
  }
};
