import { describe, expect, it } from 'vitest';

import { useSkillFileBuffers } from './use-skill-file-buffers';

describe('skill file buffers', () => {
  it('keeps independent unsaved content when switching files', () => {
    const store = useSkillFileBuffers();
    store.ensureBuffer({ content: '# Skill', path: 'SKILL.md', type: 'SKILL' });
    store.ensureBuffer({
      content: '# Policy',
      path: 'references/policy.md',
      type: 'REFERENCE',
    });

    store.updateContent('SKILL.md', '# Updated Skill');
    store.updateContent('references/policy.md', '# Updated Policy');

    expect(store.buffers.get('SKILL.md')?.content).toBe('# Updated Skill');
    expect(store.buffers.get('references/policy.md')?.content).toBe(
      '# Updated Policy',
    );
    expect([...store.dirtyPaths.value]).toEqual([
      'SKILL.md',
      'references/policy.md',
    ]);
  });

  it('only clears dirty state after the matching file is saved', () => {
    const store = useSkillFileBuffers();
    store.ensureBuffer({
      content: 'one',
      path: 'scripts/run.py',
      type: 'SCRIPT',
    });
    store.updateContent('scripts/run.py', 'two');
    expect(store.dirtyPaths.value.size).toBe(1);

    store.markSaved('scripts/run.py');
    expect(store.dirtyPaths.value.size).toBe(0);
  });

  it('keeps edits made while a save request is in flight dirty', () => {
    const store = useSkillFileBuffers();
    store.ensureBuffer({
      content: 'one',
      path: 'scripts/run.py',
      type: 'SCRIPT',
    });
    store.updateContent('scripts/run.py', 'two');
    const sentContent = store.markSaving('scripts/run.py');
    store.updateContent('scripts/run.py', 'three');

    store.markSaved(
      'scripts/run.py',
      { content: 'two', path: 'scripts/run.py', type: 'SCRIPT' },
      sentContent,
    );

    expect(store.buffers.get('scripts/run.py')?.original).toBe('two');
    expect(store.buffers.get('scripts/run.py')?.content).toBe('three');
    expect(store.buffers.get('scripts/run.py')?.saveState).toBe('dirty');
  });

  it('preserves dirty content and marks a conflict when the server refresh changes', () => {
    const store = useSkillFileBuffers();
    store.ensureBuffer({
      content: 'one',
      contentHash: 'old-hash',
      path: 'SKILL.md',
      type: 'SKILL',
    });
    store.updateContent('SKILL.md', 'local');
    store.ensureBuffer({
      content: 'remote',
      contentHash: 'remote-hash',
      path: 'SKILL.md',
      type: 'SKILL',
    });

    expect(store.buffers.get('SKILL.md')?.content).toBe('local');
    expect(store.buffers.get('SKILL.md')?.conflict).toBe(true);
    expect(store.buffers.get('SKILL.md')?.file.contentHash).toBe('old-hash');
  });

  it('rejects renaming over an existing buffer', () => {
    const store = useSkillFileBuffers();
    store.ensureBuffer({ content: 'one', path: 'a.md', type: 'REFERENCE' });
    store.ensureBuffer({ content: 'two', path: 'b.md', type: 'REFERENCE' });
    expect(() => store.renameBuffer('a.md', 'b.md')).toThrow('目标路径已存在');
  });
});
