import type { SkillFileBuffer, SkillFileContent } from './types';

import { computed, reactive } from 'vue';

export function useSkillFileBuffers() {
  const buffers = reactive(new Map<string, SkillFileBuffer>());

  const dirtyPaths = computed(
    () =>
      new Set(
        [...buffers.values()]
          .filter((buffer) => buffer.content !== buffer.original)
          .map((buffer) => buffer.file.path),
      ),
  );

  function ensureBuffer(
    file: SkillFileContent,
    refreshStrategy: 'preserve-dirty' | 'replace' = 'preserve-dirty',
  ) {
    const existing = buffers.get(file.path);
    if (existing) {
      const serverContent = file.content || '';
      const dirty = existing.content !== existing.original;
      if (refreshStrategy === 'replace' || !dirty) {
        Object.assign(existing, {
          conflict: false,
          content: serverContent,
          file,
          original: serverContent,
          pendingContent: undefined,
          saveState: 'saved',
        });
      } else {
        existing.conflict = serverContent !== existing.original;
        if (!existing.conflict) existing.file = file;
      }
      return existing;
    }
    const buffer: SkillFileBuffer = {
      content: file.content || '',
      file,
      original: file.content || '',
      revision: 0,
      saveState: 'saved',
    };
    buffers.set(file.path, buffer);
    return buffer;
  }

  function updateContent(path: string, content: string) {
    const buffer = buffers.get(path);
    if (!buffer || buffer.content === content) return;
    buffer.content = content;
    buffer.revision += 1;
    buffer.saveState = content === buffer.original ? 'saved' : 'dirty';
  }

  function markSaving(path: string) {
    const buffer = buffers.get(path);
    if (!buffer) return undefined;
    buffer.pendingContent = buffer.content;
    buffer.saveState = 'saving';
    return buffer.pendingContent;
  }

  function markSaved(
    path: string,
    file?: SkillFileContent,
    sentContent?: string,
  ) {
    const buffer = buffers.get(path);
    if (!buffer) return;
    const sent = sentContent ?? buffer.pendingContent ?? buffer.content;
    const serverContent = file?.content ?? sent;
    if (file) buffer.file = file;
    buffer.original = serverContent;
    buffer.pendingContent = undefined;
    buffer.conflict = false;
    if (buffer.content === sent) {
      buffer.content = serverContent;
      buffer.saveState = 'saved';
    } else {
      buffer.saveState = 'dirty';
    }
  }

  function markError(path: string) {
    const buffer = buffers.get(path);
    if (buffer) buffer.saveState = 'error';
  }

  function markConflict(path: string) {
    const buffer = buffers.get(path);
    if (!buffer) return;
    buffer.conflict = true;
    buffer.pendingContent = undefined;
    buffer.saveState = 'error';
  }

  function removeBuffer(path: string) {
    buffers.delete(path);
  }

  function renameBuffer(path: string, nextPath: string) {
    if (path !== nextPath && buffers.has(nextPath)) {
      throw new Error(`目标路径已存在：${nextPath}`);
    }
    const buffer = buffers.get(path);
    if (!buffer) return;
    buffers.delete(path);
    buffer.file = { ...buffer.file, path: nextPath };
    buffers.set(nextPath, buffer);
  }

  function clearBuffers() {
    buffers.clear();
  }

  return {
    buffers,
    clearBuffers,
    dirtyPaths,
    ensureBuffer,
    markConflict,
    markError,
    markSaved,
    markSaving,
    removeBuffer,
    renameBuffer,
    updateContent,
  };
}
