import { renderHook, act } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { useOverlayState } from './useOverlayState';

describe('useOverlayState', () => {
  const inspectSelection = {
    Id: 'sha256:abc123',
    RepoTags: ['nginx:latest'],
    usedByStacks: ['web'],
    nodeId: 1,
  };

  it('initialises with all overlays closed and null/empty data', () => {
    const { result } = renderHook(() => useOverlayState());
    expect(result.current.createDialogOpen).toBe(false);
    expect(result.current.deleteDialogOpen).toBe(false);
    expect(result.current.deleteTarget).toBeNull();
    expect(result.current.pendingUnsavedLoad).toBeNull();
    expect(result.current.pendingLoadOptions).toBeNull();
    expect(result.current.pendingUnsavedNode).toBeNull();
    expect(result.current.bashModalOpen).toBe(false);
    expect(result.current.selectedContainer).toBeNull();
    expect(result.current.logViewerOpen).toBe(false);
    expect(result.current.logContainer).toBeNull();
    expect(result.current.inspectImage).toBeNull();
    expect(result.current.stackMonitor).toBeNull();
    expect(result.current.policyBlock).toBeNull();
    expect(result.current.policyBypassing).toBe(false);
    expect(result.current.stackMisconfigScanId).toBeNull();
    expect(result.current.diffPreview).toBeNull();
    expect(result.current.diffPreviewConfirming).toBe(false);
  });

  it('openBashModal sets open flag and container object', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openBashModal({ id: 'abc', name: 'my-container' }));
    expect(result.current.bashModalOpen).toBe(true);
    expect(result.current.selectedContainer).toEqual({ id: 'abc', name: 'my-container' });
  });

  it('closeBashModal resets bash state', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openBashModal({ id: 'abc', name: 'my-container' }));
    act(() => result.current.closeBashModal());
    expect(result.current.bashModalOpen).toBe(false);
    expect(result.current.selectedContainer).toBeNull();
  });

  it('openDeleteDialog sets open flag and stack name', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openDeleteDialog({ name: 'my-stack', nodeId: 1 }));
    expect(result.current.deleteDialogOpen).toBe(true);
    expect(result.current.deleteTarget).toEqual({ name: 'my-stack', nodeId: 1 });
  });

  it('closeDeleteDialog resets delete state', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openDeleteDialog({ name: 'my-stack', nodeId: 1 }));
    act(() => result.current.closeDeleteDialog());
    expect(result.current.deleteDialogOpen).toBe(false);
    expect(result.current.deleteTarget).toBeNull();
  });

  it('openLogViewer sets open flag and container object', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openLogViewer({ id: 'xyz', name: 'log-container' }));
    expect(result.current.logViewerOpen).toBe(true);
    expect(result.current.logContainer).toEqual({ id: 'xyz', name: 'log-container' });
  });

  it('closeLogViewer resets log viewer state', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openLogViewer({ id: 'xyz', name: 'log-container' }));
    act(() => result.current.closeLogViewer());
    expect(result.current.logViewerOpen).toBe(false);
    expect(result.current.logContainer).toBeNull();
  });

  it('openInspectImage sets the selection', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openInspectImage(inspectSelection));
    expect(result.current.inspectImage).toEqual(inspectSelection);
  });

  it('closeInspectImage clears the selection', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openInspectImage(inspectSelection));
    act(() => result.current.closeInspectImage());
    expect(result.current.inspectImage).toBeNull();
  });

  it('openAlertSheet opens stack monitor on the alerts tab', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openAlertSheet('web-stack'));
    expect(result.current.stackMonitor).toEqual({ stackName: 'web-stack', tab: 'alerts' });
  });

  it.each([
    ['openAlertSheet', 'alerts' as const],
    ['openAutoHeal', 'auto-heal' as const],
  ])('%s can carry a serviceName for form preselect', (openFn, tab) => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current[openFn as 'openAlertSheet' | 'openAutoHeal']('web-stack', { serviceName: 'api' }));
    expect(result.current.stackMonitor).toEqual({
      stackName: 'web-stack',
      tab,
      serviceName: 'api',
    });
  });

  it('openAutoHeal opens stack monitor on the auto-heal tab', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openAutoHeal('web-stack'));
    expect(result.current.stackMonitor).toEqual({ stackName: 'web-stack', tab: 'auto-heal' });
  });

  it('openAutoHeal after openAlertSheet switches to the auto-heal tab', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openAlertSheet('web-stack'));
    act(() => result.current.openAutoHeal('web-stack'));
    expect(result.current.stackMonitor).toEqual({ stackName: 'web-stack', tab: 'auto-heal' });
  });

  it('closeStackMonitor clears the stack monitor state', () => {
    const { result } = renderHook(() => useOverlayState());
    act(() => result.current.openAlertSheet('web-stack'));
    act(() => result.current.closeStackMonitor());
    expect(result.current.stackMonitor).toBeNull();
  });

  it('pendingLoadOptions starts null, can be set, and clears independently', () => {
    const { result } = renderHook(() => useOverlayState());
    expect(result.current.pendingLoadOptions).toBeNull();
    act(() => {
      result.current.setPendingUnsavedLoad('web.yml');
      result.current.setPendingLoadOptions({ startInComposeEdit: true });
    });
    expect(result.current.pendingUnsavedLoad).toBe('web.yml');
    expect(result.current.pendingLoadOptions).toEqual({ startInComposeEdit: true });
    act(() => {
      result.current.setPendingUnsavedLoad(null);
      result.current.setPendingLoadOptions(null);
    });
    expect(result.current.pendingUnsavedLoad).toBeNull();
    expect(result.current.pendingLoadOptions).toBeNull();
  });
});
