/**
 * Bug 2 fix verification: 删除引用后，同类型剩余引用连续重命名（即梦逻辑）
 * 同时同步更新 editorHtml 中 @mention span 的文本。
 */
import { describe, it, expect, beforeEach } from 'vitest';
import { useInputBarStore } from '../../src/store/inputBar';

function mockFile(name: string, type = 'image/jpeg'): File {
  return new File(['mock'], name, { type });
}

function mockRef(id: string, type: 'image' | 'video' | 'audio', label: string) {
  return {
    id,
    file: mockFile(`${id}.${type === 'image' ? 'jpg' : type === 'video' ? 'mp4' : 'mp3'}`),
    type,
    previewUrl: `blob:${id}`,
    label,
  };
}

function mentionSpan(refId: string, refType: string, label: string): string {
  return `<span data-ref-id="${refId}" data-ref-type="${refType}" class="mention" contenteditable="false"><span style="font-size:0;width:0;overflow:hidden;display:inline">@</span>${label}</span>`;
}

describe('removeReference — 即梦式连续重命名', () => {
  beforeEach(() => {
    useInputBarStore.getState().reset();
  });

  describe('图片重命名', () => {
    it('删除图片2 后，图片3 重命名为图片2（references + editorHtml 同步）', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
        mockRef('ref_3', 'image', '图片3'),
      ];
      const editorHtml =
        `开场 ${mentionSpan('ref_1', 'image', '图片1')} 和 ${mentionSpan('ref_2', 'image', '图片2')} 在和 ${mentionSpan('ref_3', 'image', '图片3')} 讲话`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_2');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(2);
      expect(state.references[0].id).toBe('ref_1');
      expect(state.references[0].label).toBe('图片1');
      expect(state.references[1].id).toBe('ref_3');
      expect(state.references[1].label).toBe('图片2'); // 原图片3 → 图片2

      // editorHtml 里 ref_3 的 textNode 应该变成 "图片2"
      expect(state.editorHtml).toContain('data-ref-id="ref_3"');
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?图片2<\/span>/);
      // ref_1 保持 "图片1"
      expect(state.editorHtml).toMatch(/data-ref-id="ref_1"[^>]*>[\s\S]*?图片1<\/span>/);
    });

    it('删除图片1 后，图片2、图片3 重命名为图片1、图片2', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
        mockRef('ref_3', 'image', '图片3'),
      ];
      const editorHtml = `${mentionSpan('ref_2', 'image', '图片2')} ${mentionSpan('ref_3', 'image', '图片3')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references[0].label).toBe('图片1'); // ref_2
      expect(state.references[1].label).toBe('图片2'); // ref_3
      expect(state.editorHtml).toMatch(/data-ref-id="ref_2"[^>]*>[\s\S]*?图片1<\/span>/);
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?图片2<\/span>/);
    });

    it('删除最后一张图片（唯一图片）— references 清空，editorHtml 不变', () => {
      const refs = [mockRef('ref_1', 'image', '图片1')];
      const editorHtml = `内容 ${mentionSpan('ref_1', 'image', '图片1')} 尾部`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(0);
      // remaining 为空 → labelUpdates 为空 → 跳过 DOM 操作 → editorHtml 原样保留
      expect(state.editorHtml).toBe(editorHtml);
    });
  });

  describe('视频/音频独立编号', () => {
    it('图片和视频混合时，删图片只重命名图片，视频不动', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
        mockRef('ref_3', 'video', '视频1'),
      ];
      const editorHtml =
        `${mentionSpan('ref_1', 'image', '图片1')} ${mentionSpan('ref_2', 'image', '图片2')} ${mentionSpan('ref_3', 'video', '视频1')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(2);
      expect(state.references[0].label).toBe('图片1'); // 原图片2
      expect(state.references[1].label).toBe('视频1'); // 视频不变
      expect(state.editorHtml).toMatch(/data-ref-id="ref_2"[^>]*>[\s\S]*?图片1<\/span>/);
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?视频1<\/span>/);
    });

    it('删除视频2，视频3 重命名为视频2', () => {
      const refs = [
        mockRef('ref_1', 'video', '视频1'),
        mockRef('ref_2', 'video', '视频2'),
        mockRef('ref_3', 'video', '视频3'),
      ];
      const editorHtml = `${mentionSpan('ref_3', 'video', '视频3')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_2');

      const state = useInputBarStore.getState();
      expect(state.references[0].label).toBe('视频1');
      expect(state.references[1].label).toBe('视频2'); // 原视频3
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?视频2<\/span>/);
    });

    it('删除音频1，音频2 重命名为音频1', () => {
      const refs = [
        mockRef('ref_1', 'audio', '音频1'),
        mockRef('ref_2', 'audio', '音频2'),
      ];
      const editorHtml = `${mentionSpan('ref_1', 'audio', '音频1')} ${mentionSpan('ref_2', 'audio', '音频2')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(1);
      expect(state.references[0].id).toBe('ref_2');
      expect(state.references[0].label).toBe('音频1'); // 原音频2
      expect(state.editorHtml).toMatch(/data-ref-id="ref_2"[^>]*>[\s\S]*?音频1<\/span>/);
    });
  });

  describe('边界场景', () => {
    it('editorHtml 为空 — 不报错，只重命名 references', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
      ];
      useInputBarStore.setState({ references: refs, editorHtml: '' });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(1);
      expect(state.references[0].label).toBe('图片1');
      expect(state.editorHtml).toBe('');
    });

    it('editorHtml 中没有对应的 @mention span — 只改 references', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
      ];
      const editorHtml = '<span>纯文本，没有 mention span</span>';

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(1);
      expect(state.references[0].label).toBe('图片1'); // ref_2 重命名
      // editorHtml 不含对应 span，无法更新，但不报错
    });

    it('传入不存在的 id — 静默返回，状态不变', () => {
      const refs = [mockRef('ref_1', 'image', '图片1')];
      const editorHtml = mentionSpan('ref_1', 'image', '图片1');

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('nonexistent_id');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(1);
      expect(state.references[0].label).toBe('图片1');
      expect(state.editorHtml).toBe(editorHtml);
    });

    it('删除的图片没被 @ 到 editor，其他图片仍被重命名', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
        mockRef('ref_3', 'image', '图片3'),
      ];
      // editorHtml 只 @ 了图片3，没 @图片1/2
      const editorHtml = `${mentionSpan('ref_3', 'image', '图片3')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references[0].label).toBe('图片1'); // 原图片2
      expect(state.references[1].label).toBe('图片2'); // 原图片3
      // editor 里只有 ref_3 的 span，应该更新成"图片2"
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?图片2<\/span>/);
    });
  });

  describe('连续删除（并发）', () => {
    it('连续删除两张图片，剩余图片正确重编号', () => {
      const refs = [
        mockRef('ref_1', 'image', '图片1'),
        mockRef('ref_2', 'image', '图片2'),
        mockRef('ref_3', 'image', '图片3'),
        mockRef('ref_4', 'image', '图片4'),
      ];
      const editorHtml = `${mentionSpan('ref_1', 'image', '图片1')} ${mentionSpan('ref_2', 'image', '图片2')} ${mentionSpan('ref_3', 'image', '图片3')} ${mentionSpan('ref_4', 'image', '图片4')}`;

      useInputBarStore.setState({ references: refs, editorHtml });
      useInputBarStore.getState().removeReference('ref_2');
      useInputBarStore.getState().removeReference('ref_1');

      const state = useInputBarStore.getState();
      expect(state.references).toHaveLength(2);
      expect(state.references[0].id).toBe('ref_3');
      expect(state.references[0].label).toBe('图片1');
      expect(state.references[1].id).toBe('ref_4');
      expect(state.references[1].label).toBe('图片2');
      expect(state.editorHtml).toMatch(/data-ref-id="ref_3"[^>]*>[\s\S]*?图片1<\/span>/);
      expect(state.editorHtml).toMatch(/data-ref-id="ref_4"[^>]*>[\s\S]*?图片2<\/span>/);
    });
  });
});
