import type { ISessionMetaRepository, ExecutionSummary } from '../../interfaces/repositories/session-meta-repository';
import type { SessionMeta, SessionState } from '../../interfaces/core/types';

export class SessionMetaRepository implements ISessionMetaRepository {
  private sessions = new Map<string, SessionMeta>();

  save(sessionMeta: SessionMeta): void {
    this.sessions.set(sessionMeta.label, sessionMeta);
  }

  findByLabel(label: string): SessionMeta | null {
    return this.sessions.get(label) || null;
  }

  findAll(): SessionMeta[] {
    return Array.from(this.sessions.values());
  }

  delete(label: string): boolean {
    return this.sessions.delete(label);
  }

  clear(): void {
    this.sessions.clear();
  }

  exists(label: string): boolean {
    return this.sessions.has(label);
  }

  updateState(label: string, state: Partial<SessionState>): void {
    const session = this.sessions.get(label);
    if (session) {
      Object.assign(session, state);
    }
  }

  getStates(): Record<string, SessionState> {
    const states: Record<string, SessionState> = {};
    this.sessions.forEach((meta, label) => {
      states[label] = {
        label: meta.label,
        status: meta.status,
        ...(meta.timestamp && { timestamp: meta.timestamp }),
        ...(meta.duration && { duration: meta.duration })
      };
    });
    return states;
  }

  markAsRunning(label: string): void {
    this.updateState(label, { status: 'running', timestamp: new Date() });
  }

  markAsCompleted(label: string, result: any): void {
    this.updateState(label, { 
      status: 'passed', 
      timestamp: new Date(),
      duration: result.duration
    });
  }

  markAsFailed(label: string, error: Error): void {
    const session = this.sessions.get(label);
    if (session) {
      session.status = 'failed';
      session.error = error;
      session.timestamp = new Date();
    }
  }

  getByStatus(status: SessionState['status']): SessionMeta[] {
    return this.findAll().filter(session => session.status === status);
  }

  getExecutionSummary(): ExecutionSummary {
    const all = this.findAll();
    const lastExecutionTime = all.reduce((latest, session) => {
      if (session.timestamp && (!latest || session.timestamp > latest)) {
        return session.timestamp;
      }
      return latest;
    }, undefined as Date | undefined);

    return {
      totalSessions: all.length,
      readySessions: all.filter(s => s.status === 'ready').length,
      runningSessions: all.filter(s => s.status === 'running').length,
      completedSessions: all.filter(s => s.status === 'passed').length,
      failedSessions: all.filter(s => s.status === 'failed').length,
      ...(lastExecutionTime && { lastExecutionTime })
    };
  }
}
