import { describe, it, expect, vi, beforeEach } from 'vitest';
import { join } from 'node:path';

const { handlers, mockOpenPath } = vi.hoisted(() => ({
  handlers: {} as Record<string, (...args: unknown[]) => unknown>,
  mockOpenPath: vi.fn(async () => '')
}));

vi.mock('electron', () => ({
  default: {
    ipcMain: {
      handle: (ch: string, fn: (...args: unknown[]) => unknown) => {
        handlers[ch] = fn;
      },
      on: (_ch: string, _fn: unknown) => {}
    },
    dialog: {},
    shell: { openPath: mockOpenPath }
  }
}));

import { registerInboxApi } from '../../src/main/ipc/inboxApi';

function makeDeps(profileDir: string): Parameters<typeof registerInboxApi>[0] {
  // Minimal stub — `inbox:open-media` 핸들러는 deps.paths.profileDir 만 참조.
  return {
    repo: {} as never,
    continuity: {} as never,
    capture: {} as never,
    health: {} as never,
    intent: {} as never,
    getInboxWindow: () => null,
    settings: {} as never,
    providerHolder: {} as never,
    paths: { profileDir }
  };
}

describe('inbox:open-media IPC', () => {
  beforeEach(() => {
    Object.keys(handlers).forEach((k) => delete handlers[k]);
    mockOpenPath.mockClear();
  });

  it('opens valid relPath with shell.openPath', async () => {
    registerInboxApi(makeDeps('/profile'));
    const handler = handlers['inbox:open-media'];
    if (handler === undefined) throw new Error('handler not registered');
    const r = await handler(null, 'media/note1/img.png');
    expect(r).toEqual({ ok: true });
    expect(mockOpenPath).toHaveBeenCalledWith(join('/profile', 'media', 'note1', 'img.png'));
  });

  it('rejects path traversal with reason "invalid path"', async () => {
    registerInboxApi(makeDeps('/profile'));
    const handler = handlers['inbox:open-media'];
    if (handler === undefined) throw new Error('handler not registered');
    const r = await handler(null, '../etc/passwd') as { ok: boolean; reason?: string };
    expect(r.ok).toBe(false);
    expect(r.reason).toBe('invalid path');
    expect(mockOpenPath).not.toHaveBeenCalled();
  });
});
