// Sync service - manages offline mutation queueing
//
// Simplified service that coordinates with the Rust backend.
// The Rust backend handles sync queue persistence and processing logic.
// This service provides a thin TypeScript API for queuing mutations.
//
// TRACES: UR-002, UR-017, UR-025 | DR-014

import { commands } from "$lib/api/bindings";
import { auth } from "$lib/stores/auth";

// Types matching Rust structs
export interface SyncQueueItem {
  id: number;
  userId: string;
  operation: string;
  itemId: string | null;
  payload: string | null;
  status: string;
  retryCount: number;
  createdAt: string | null;
  errorMessage: string | null;
}

export type SyncOperation =
  | "mark_played"
  | "mark_favorite"
  | "unmark_favorite"
  | "update_progress"
  | "report_playback_start"
  | "report_playback_stopped"
  | "playlist_create"
  | "playlist_delete"
  | "playlist_rename"
  | "playlist_add_items"
  | "playlist_remove_items"
  | "playlist_reorder_item";

/**
 * Simplified sync service - handles offline mutation queueing
 *
 * The Rust backend maintains the sync queue in SQLite and is responsible
 * for processing queued items. This service provides a TypeScript API
 * for queueing and managing sync operations.
 */
class SyncService {
  /**
   * Start the sync service (lifecycle managed by Rust backend)
   */
  start(): void {
    console.log("[SyncService] Started");
  }

  /**
   * Stop the sync service (lifecycle managed by Rust backend)
   */
  stop(): void {
    console.log("[SyncService] Stopped");
  }

  /**
   * Queue a mutation for sync to server
   *
   * TRACES: UR-017, UR-025 | DR-014
   */
  async queueMutation(
    operation: SyncOperation,
    itemId: string,
    payload?: Record<string, unknown>
  ): Promise<number> {
    const userId = auth.getUserId();
    if (!userId) {
      throw new Error("Not authenticated");
    }

    const id = await commands.syncQueueMutation(
      userId,
      operation,
      itemId,
      payload ? JSON.stringify(payload) : null
    );

    console.log(`[SyncService] Queued ${operation} for item ${itemId}, id: ${id}`);
    return id;
  }

  /**
   * Queue a favorite toggle
   * Also updates local state immediately
   */
  async queueFavorite(itemId: string, isFavorite: boolean): Promise<number> {
    // Update local state first
    await commands.storageToggleFavorite(auth.getUserId() ?? "", itemId, isFavorite);

    return this.queueMutation(
      isFavorite ? "mark_favorite" : "unmark_favorite",
      itemId
    );
  }

  /**
   * Queue playback progress update
   * Also updates local state immediately
   */
  async queuePlaybackProgress(
    itemId: string,
    positionTicks: number
  ): Promise<number> {
    // Update local state first
    await commands.storageUpdatePlaybackProgress(auth.getUserId() ?? "", itemId, positionTicks);

    return this.queueMutation("update_progress", itemId, { positionTicks });
  }

  /**
   * Queue mark as played
   * Also updates local state immediately
   */
  async queueMarkPlayed(itemId: string): Promise<number> {
    // Update local state first
    await commands.storageMarkPlayed(auth.getUserId() ?? "", itemId);

    return this.queueMutation("mark_played", itemId);
  }

  /**
   * Get count of pending sync operations
   */
  async getPendingCount(): Promise<number> {
    const userId = auth.getUserId();
    if (!userId) {
      return 0;
    }

    return commands.syncGetPendingCount(userId);
  }

  /**
   * Get pending sync items (for debugging/monitoring)
   */
  async getPending(limit?: number): Promise<SyncQueueItem[]> {
    const userId = auth.getUserId();
    if (!userId) {
      return [];
    }

    return commands.syncGetPending(userId, limit ?? null);
  }

  /**
   * Clean up completed operations older than specified days
   */
  async cleanup(daysOld: number = 7): Promise<number> {
    const deleted = await commands.syncCleanupCompleted(daysOld);
    console.log(`[SyncService] Cleaned up ${deleted} old completed operations`);
    return deleted;
  }

  // ===== Playlist sync operations =====

  async queuePlaylistCreate(playlistId: string, name: string, itemIds: string[]): Promise<number> {
    return this.queueMutation("playlist_create", playlistId, { name, itemIds });
  }

  async queuePlaylistDelete(playlistId: string): Promise<number> {
    return this.queueMutation("playlist_delete", playlistId);
  }

  async queuePlaylistRename(playlistId: string, name: string): Promise<number> {
    return this.queueMutation("playlist_rename", playlistId, { name });
  }

  async queuePlaylistAddItems(playlistId: string, itemIds: string[]): Promise<number> {
    return this.queueMutation("playlist_add_items", playlistId, { itemIds });
  }

  async queuePlaylistRemoveItems(playlistId: string, entryIds: string[]): Promise<number> {
    return this.queueMutation("playlist_remove_items", playlistId, { entryIds });
  }

  async queuePlaylistReorderItem(playlistId: string, itemId: string, newIndex: number): Promise<number> {
    return this.queueMutation("playlist_reorder_item", playlistId, { itemId, newIndex });
  }

  /**
   * Clear all sync operations for the current user (called during logout)
   *
   * TRACES: UR-017 | DR-014
   */
  async clearUser(): Promise<void> {
    const userId = auth.getUserId();
    if (userId) {
      await commands.syncClearUser(userId);
      console.log("[SyncService] Cleared sync queue for user");
    }
  }
}

// Export singleton instance
export const syncService = new SyncService();
