import { Program } from '../../engine';
import { IStorageService, StoredProgramSummary } from './storage-interface';

/**
 * A simulated Backend storage service.
 * In a real application, this would make fetch/axios calls to a remote API.
 * We simulate network latency and occasional errors to test robustness.
 */
export class BackendStorageService implements IStorageService {
  // Using an in-memory map to simulate the server-side database
  private remoteDatabase: Map<string, { program: Program; lastModified: number }> = new Map();

  private async simulateNetwork() {
    const latency = Math.random() * 300 + 100; // 100-400ms latency
    await new Promise((resolve) => setTimeout(resolve, latency));

    // Simulate occasional network errors (e.g., 5% chance)
    if (Math.random() < 0.05) {
      throw new Error('Network Error: Failed to connect to backend');
    }
  }

  async saveProgram(program: Program, id?: string): Promise<string> {
    await this.simulateNetwork();
    const programId = id || crypto.randomUUID();
    this.remoteDatabase.set(programId, {
      program: { ...program },
      lastModified: Date.now(),
    });
    return programId;
  }

  async loadProgram(id: string): Promise<Program> {
    await this.simulateNetwork();
    const entry = this.remoteDatabase.get(id);
    if (!entry) {
      throw new Error(`Backend Error: Program with id ${id} not found`);
    }
    return { ...entry.program };
  }

  async listPrograms(): Promise<StoredProgramSummary[]> {
    await this.simulateNetwork();
    const summaries: StoredProgramSummary[] = [];
    this.remoteDatabase.forEach((entry, id) => {
      summaries.push({
        id,
        name: entry.program.name,
        lastModified: entry.lastModified,
      });
    });
    // Sort by last modified descending
    return summaries.sort((a, b) => b.lastModified - a.lastModified);
  }

  async deleteProgram(id: string): Promise<void> {
    await this.simulateNetwork();
    if (!this.remoteDatabase.has(id)) {
      throw new Error(`Backend Error: Cannot delete. Program with id ${id} not found`);
    }
    this.remoteDatabase.delete(id);
  }

  async renameProgram(id: string, newName: string): Promise<void> {
    await this.simulateNetwork();
    const entry = this.remoteDatabase.get(id);
    if (!entry) {
      throw new Error(`Backend Error: Cannot rename. Program with id ${id} not found`);
    }
    entry.program.name = newName;
    entry.lastModified = Date.now();
    this.remoteDatabase.set(id, entry);
  }
}