import { act, renderHook, waitFor } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import useShareUrl from './use-share-preview';
import * as api from '../api';

vi.mock('../api', () => ({
  enablePreviewMode: vi.fn(async () => undefined),
  disablePreviewMode: vi.fn(async () => undefined),
  createPreviewShareUrl: vi.fn(async () => 'https://example.test/share'),
}));

describe('useShareUrl', () => {
  afterEach(() => {
    const emit = window.ACMS.events.emit as ReturnType<typeof vi.fn>;
    emit.mockClear();
    emit.mockImplementation(async (_type: string, payload: unknown) => ({ canceled: false, event: payload }));
    vi.mocked(api.createPreviewShareUrl).mockClear();
  });

  it('ハンドラ0件でも従来どおり preview.share.before → createPreviewShareUrl → preview.share.success の順で成功する（特徴付けテスト）', async () => {
    const { result } = renderHook(() => useShareUrl());

    await act(async () => {
      await result.current.createShareUrl('https://example.test/page');
    });

    const emit = window.ACMS.events.emit as ReturnType<typeof vi.fn>;
    expect(emit).toHaveBeenNthCalledWith(1, 'preview.share.before', { formData: expect.any(FormData) });
    expect(api.createPreviewShareUrl).toHaveBeenCalled();
    expect(emit).toHaveBeenNthCalledWith(2, 'preview.share.success', { shareUrl: 'https://example.test/share' });
    await waitFor(() => expect(result.current.status).toBe('done'));
    expect(result.current.shareUrl).toBe('https://example.test/share');
  });

  it('preview.share.before がキャンセルされた場合は createPreviewShareUrl を呼ばず standby に戻す', async () => {
    (window.ACMS.events.emit as ReturnType<typeof vi.fn>).mockImplementation(async () => ({
      canceled: true,
      reason: 'blocked',
      event: {},
    }));
    const { result } = renderHook(() => useShareUrl());

    await act(async () => {
      await result.current.createShareUrl('https://example.test/page');
    });

    expect(api.createPreviewShareUrl).not.toHaveBeenCalled();
    expect(result.current.status).toBe('standby');
    expect(result.current.error).toBe('blocked');
  });

  describe('ACMS.events 未初期化時（プレビュー共有ページ等、管理画面バンドル非ロード）', () => {
    it('例外を投げずに createPreviewShareUrl が実行され done になる（ハンドラ0件と同じ素通し扱い）', async () => {
      const originalEvents = window.ACMS.events;
      // @ts-expect-error テスト用に未初期化状態を再現する
      delete window.ACMS.events;
      try {
        const { result } = renderHook(() => useShareUrl());

        await act(async () => {
          await result.current.createShareUrl('https://example.test/page');
        });

        expect(api.createPreviewShareUrl).toHaveBeenCalled();
        await waitFor(() => expect(result.current.status).toBe('done'));
      } finally {
        window.ACMS.events = originalEvents;
      }
    });
  });
});
