import {
  type ProjectSchema,
  type BlockSchema,
  type HistorySchema,
  type HistoryItem,
  type MaterialDescription,
  ProjectModel,
  HistoryModel
} from '@vtj/core';

import { mapToObject } from '@vtj/utils';
import { BaseService } from '@vtj/renderer';

export class MemoryService extends BaseService {
  private projects: Record<string, ProjectSchema> = {};
  private materials: Record<string, Record<string, MaterialDescription>> = {};
  private files: Record<string, BlockSchema> = {};
  private histories: Record<string, HistorySchema> = {};
  private historyItems: Record<string, HistoryItem> = {};

  public init(project: ProjectSchema): Promise<ProjectSchema> {
    console.log('MemoryService.init', { project });
    const model = new ProjectModel(project);
    const match = this.projects[model.id] || {};
    const dsl = Object.assign(model.toDsl(), match);
    this.projects[dsl.id as string] = dsl;
    console.log('MemoryService.init result', { dsl });
    return Promise.resolve(dsl);
  }

  public saveProject(project: ProjectSchema): Promise<boolean> {
    console.log('MemoryService.saveProject', { project });
    const model = new ProjectModel(project);
    this.projects[model.id] = model.toDsl();
    console.log('MemoryService.saveProject result', { success: true });
    return Promise.resolve(true);
  }

  public saveMaterials(
    project: ProjectSchema,
    materials: Map<string, MaterialDescription>
  ): Promise<boolean> {
    console.log('MemoryService.saveMaterials', { project, materials });
    if (project.id) {
      this.materials[project.id] = mapToObject(materials);
    }
    console.log('MemoryService.saveMaterials result', { success: true });
    return Promise.resolve(true);
  }

  public saveFile(file: BlockSchema): Promise<boolean> {
    console.log('MemoryService.saveFile', { file });
    this.files[file.id as string] = file;
    console.log('MemoryService.saveFile result', { success: true });
    return Promise.resolve(true);
  }

  public getFile(id: string): Promise<BlockSchema> {
    console.log('MemoryService.getFile', { id });
    const file = this.files[id];
    console.log('MemoryService.getFile result', { file });
    return file ? Promise.resolve(file) : Promise.reject(null);
  }

  public removeFile(id: string): Promise<boolean> {
    console.log('MemoryService.removeFile', { id });
    delete this.files[id];
    console.log('MemoryService.removeFile result', { success: true });
    return Promise.resolve(true);
  }

  public saveHistory(history: HistorySchema): Promise<boolean> {
    console.log('MemoryService.saveHistory', { history });
    this.histories[history.id] = history;
    console.log('MemoryService.saveHistory result', { success: true });
    return Promise.resolve(true);
  }

  public removeHistory(id: string): Promise<boolean> {
    console.log('MemoryService.removeHistory', { id });
    const history = this.histories[id] as HistorySchema;
    if (history) {
      const items = history.items || [];
      const ids = items.map((item) => item.id);
      this.removeHistoryItem(id, ids);
      delete this.historyItems[id];
    }
    console.log('MemoryService.removeHistory result', { success: true });
    return Promise.resolve(true);
  }

  public getHistory(id: string): Promise<HistorySchema> {
    console.log('MemoryService.getHistory', { id });
    const dsl = this.histories[id];
    const history = new HistoryModel(dsl || { id });
    console.log('MemoryService.getHistory result', { history });
    return Promise.resolve(history);
  }

  public getHistoryItem(fId: string, id: string): Promise<HistoryItem> {
    console.log('MemoryService.getHistoryItem', { fId, id });
    const key = `${fId}_${id}`;
    const item = this.historyItems[key] || {};
    console.log('MemoryService.getHistoryItem result', { item });
    return Promise.resolve(item);
  }

  public saveHistoryItem(fId: string, item: HistoryItem): Promise<boolean> {
    console.log('MemoryService.saveHistoryItem', { fId, item });
    const key = `${fId}_${item.id}`;
    this.historyItems[key] = item;
    console.log('MemoryService.saveHistoryItem result', { success: true });
    return Promise.resolve(true);
  }

  public removeHistoryItem(fId: string, ids: string[]): Promise<boolean> {
    console.log('MemoryService.removeHistoryItem', { fId, ids });
    ids.forEach((id) => {
      const key = `${fId}_${id}`;
      delete this.historyItems[key];
    });
    console.log('MemoryService.removeHistoryItem result', { success: true });
    return Promise.resolve(true);
  }
}

let serviceInstance: MemoryService | null = null;

export function createMemoryService() {
  if (serviceInstance) return serviceInstance;
  {
    serviceInstance = new MemoryService();
    return serviceInstance;
  }
}
