/**
 * In-memory run store implementation
 * Stores runs in a Map - data is lost on restart
 */

import { RunStore } from './runStore.js';
import { Run, CreateRunData, UpdateRunData, ListRunsFilter, RunStatus } from './types.js';

export class MemoryRunStore implements RunStore {
  private runs: Map<string, Run> = new Map();

  async createRun(data: CreateRunData): Promise<Run> {
    const now = new Date().toISOString();
    const runId = data.id || `run-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    
    const run: Run = {
      id: runId,
      name: data.name || 'Test Run',
      status: 'created',
      input: data.input || null,
      output: null,
      logs: [],
      clientToken: data.clientToken || null,
      tags: data.tags || [],
      startedAt: null,
      completedAt: null,
      createdAt: now,
      updatedAt: now,
    };

    this.runs.set(runId, run);
    return run;
  }

  async getRunById(id: string): Promise<Run | null> {
    return this.runs.get(id) || null;
  }

  async getRunByClientToken(clientToken: string): Promise<Run | null> {
    for (const run of this.runs.values()) {
      if (run.clientToken === clientToken) {
        return run;
      }
    }
    return null;
  }

  async listRuns(filter?: ListRunsFilter): Promise<Run[]> {
    let runs = Array.from(this.runs.values());

    if (filter?.tag) {
      runs = runs.filter(run => run.tags?.includes(filter.tag!));
    }

    if (filter?.status) {
      runs = runs.filter(run => run.status === filter.status);
    }

    // Sort by createdAt descending (newest first)
    runs.sort((a, b) => 
      new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
    );

    if (filter?.limit) {
      runs = runs.slice(0, filter.limit);
    }

    return runs;
  }

  async updateRunStatus(
    id: string,
    status: RunStatus,
    extra?: UpdateRunData
  ): Promise<void> {
    const run = this.runs.get(id);
    if (!run) {
      throw new Error(`Run not found: ${id}`);
    }

    run.status = status;
    run.updatedAt = new Date().toISOString();

    if (extra) {
      if (extra.input !== undefined) run.input = extra.input;
      if (extra.output !== undefined) run.output = extra.output;
      if (extra.logs !== undefined) run.logs = extra.logs;
      if (extra.startedAt !== undefined) run.startedAt = extra.startedAt;
      if (extra.completedAt !== undefined) run.completedAt = extra.completedAt;
    }

    // Auto-set timestamps based on status
    if (status === 'running' && !run.startedAt) {
      run.startedAt = new Date().toISOString();
    }
    if ((status === 'completed' || status === 'failed') && !run.completedAt) {
      run.completedAt = new Date().toISOString();
    }
  }

  async deleteRun(id: string): Promise<void> {
    this.runs.delete(id);
  }
}

