import { createPinia, setActivePinia } from 'pinia';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { fetchFillData } from '../../src/api/template-fill';
import { useTemplateFiller } from '../../src/composables/useTemplateFiller';
import type { OnlyOfficeBridge } from '../../src/onlyoffice/bridge';

vi.mock('../../src/api/template-fill', () => ({ fetchFillData: vi.fn() }));

const context = {
  apiBaseUrl: 'http://localhost:30000',
  bizDataId: 'record-1',
  bizModule: 'eln.template',
  bizScene: 'eln.template.fill',
  canFill: true,
  documentId: 'file-1',
  pluginVersion: '0.1.0',
  scope: 'onlyoffice:eln-template-fill',
  ticket: 'opaque-ticket',
};

function fixture(overrides: Partial<OnlyOfficeBridge> = {}) {
  let ready = () => undefined;
  const bridge: OnlyOfficeBridge = {
    applyFields: vi.fn().mockResolvedValue([]),
    bindLifecycle: vi.fn((callbacks) => {
      ready = callbacks.onReady;
      return vi.fn();
    }),
    getRuntimeOptions: vi.fn(() => context),
    inspectFields: vi.fn().mockResolvedValue([
      { alias: '名称', currentValue: '', internalId: '1', options: [], tag: 'eln.field.name', type: 'text' },
    ]),
    ...overrides,
  };
  const filler = useTemplateFiller(bridge);
  return { bridge, filler, ready: () => ready() };
}

describe('useTemplateFiller', () => {
  beforeEach(() => {
    setActivePinia(createPinia());
    vi.mocked(fetchFillData).mockReset().mockResolvedValue({ fields: {} });
  });

  it('enters an error state when SDK initialization times out', async () => {
    vi.useFakeTimers();
    const { filler } = fixture();

    await vi.advanceTimersByTimeAsync(5_000);

    expect(filler.store.status).toBe('error');
    expect(filler.store.message).toBe('ONLYOFFICE SDK 初始化超时');
    vi.useRealTimers();
  });

  it('reports an apply failure instead of remaining in working state', async () => {
    const applyFields = vi.fn().mockRejectedValue(new Error('文档写入失败'));
    const { filler, ready } = fixture({ applyFields });
    ready();
    await vi.waitFor(() => expect(filler.store.status).toBe('ready'));
    filler.store.setDraft('eln.field.name', '样品');

    await filler.apply();

    expect(filler.store.status).toBe('error');
    expect(filler.store.message).toBe('文档写入失败');
  });

  it('does not apply changes when canFill is false', async () => {
    const applyFields = vi.fn().mockResolvedValue([]);
    const { filler, ready } = fixture({ applyFields, getRuntimeOptions: () => ({ ...context, canFill: false }) });
    ready();
    await vi.waitFor(() => expect(filler.store.status).toBe('ready'));
    filler.store.setDraft('eln.field.name', '样品');

    await filler.apply();

    expect(applyFields).not.toHaveBeenCalled();
  });
});
