import { describe, expect, it, vi } from 'vitest';
import type { ToolSession } from '../../../../src/context/tools/tool-session.js';
import { createTouchedSlSources } from '../../../../src/context/tools/touched-sl-sources.js';
import type { ToolContext } from '../../../../src/context/tools/base-tool.js';
import { WikiRemoveTool } from '../../../../src/context/wiki/tools/wiki-remove.tool.js';

describe('WikiRemoveTool', () => {
  const baseContext: ToolContext = { sourceId: 's', messageId: 'm', userId: 'u' };

  it('removes an existing page when no session is present', async () => {
    const wikiService = {
      deletePage: vi.fn().mockResolvedValue(undefined),
      deleteFromIndex: vi.fn().mockResolvedValue(undefined),
    };
    const pagesRepository = {
      findPageByKey: vi.fn().mockResolvedValue({ page_key: 'old' }),
    };
    const knowledgeRepository = { createEvent: vi.fn().mockResolvedValue(undefined) };
    const tool = new WikiRemoveTool(wikiService as any, pagesRepository as any, knowledgeRepository as any);
    const result = await tool.call({ key: 'old' } as any, baseContext);
    expect(wikiService.deletePage).toHaveBeenCalledTimes(1);
    expect(wikiService.deleteFromIndex).toHaveBeenCalledTimes(1);
    expect(result.markdown).toMatch(/removed/i);
  });

  it('rejects slash-delimited page keys with a flat-key suggestion', async () => {
    const wikiService = {
      deletePage: vi.fn().mockResolvedValue(undefined),
      deleteFromIndex: vi.fn().mockResolvedValue(undefined),
    };
    const pagesRepository = { findPageByKey: vi.fn().mockResolvedValue({ page_key: 'old' }) };
    const knowledgeRepository = { createEvent: vi.fn().mockResolvedValue(undefined) };
    const tool = new WikiRemoveTool(wikiService as any, pagesRepository as any, knowledgeRepository as any);

    const result = await tool.call({ key: 'orbit/company-overview' } as any, baseContext);

    expect(result.structured).toEqual({ success: false, key: 'orbit/company-overview' });
    expect(result.markdown).toContain(
      'Invalid wiki key "orbit/company-overview". Wiki keys must be flat; use "orbit-company-overview".',
    );
    expect(pagesRepository.findPageByKey).not.toHaveBeenCalled();
    expect(wikiService.deletePage).not.toHaveBeenCalled();
  });

  it('skips deleteFromIndex when session is worktree-scoped', async () => {
    const wikiService = {
      readPage: vi.fn().mockResolvedValue({ pageKey: 'old', frontmatter: { summary: 'Old' }, content: 'body' }),
      deletePage: vi.fn().mockResolvedValue(undefined),
      deleteFromIndex: vi.fn().mockResolvedValue(undefined),
    };
    const pagesRepository = { findPageByKey: vi.fn().mockResolvedValue({ page_key: 'old' }) };
    const knowledgeRepository = { createEvent: vi.fn().mockResolvedValue(undefined) };
    const tool = new WikiRemoveTool(wikiService as any, pagesRepository as any, knowledgeRepository as any);
    const session: ToolSession = {
      connectionId: 'c',
      isWorktreeScoped: true,
      preHead: null,
      touchedSlSources: createTouchedSlSources(),
      actions: [],
      semanticLayerService: {} as any,
      wikiService: wikiService as any,
      configService: {} as any,
      gitService: {} as any,
    };
    await tool.call({ key: 'old' } as any, { ...baseContext, session });
    expect(wikiService.deletePage).toHaveBeenCalledTimes(1);
    expect(wikiService.deleteFromIndex).not.toHaveBeenCalled();
    expect(session.actions).toContainEqual(expect.objectContaining({ target: 'wiki', type: 'removed', key: 'old' }));
  });

  it('finds pages through the session wiki service even when the shared index has not seen the worktree write', async () => {
    const wikiService = {
      readPage: vi.fn().mockResolvedValue({ pageKey: 'staged', frontmatter: { summary: 'Staged' }, content: 'body' }),
      deletePage: vi.fn().mockResolvedValue(undefined),
      deleteFromIndex: vi.fn().mockResolvedValue(undefined),
    };
    const pagesRepository = { findPageByKey: vi.fn().mockResolvedValue(null) };
    const knowledgeRepository = { createEvent: vi.fn().mockResolvedValue(undefined) };
    const tool = new WikiRemoveTool(wikiService as any, pagesRepository as any, knowledgeRepository as any);
    const session: ToolSession = {
      connectionId: 'c',
      isWorktreeScoped: true,
      preHead: null,
      touchedSlSources: createTouchedSlSources(),
      actions: [],
      semanticLayerService: {} as any,
      wikiService: wikiService as any,
      configService: {} as any,
      gitService: {} as any,
    };

    const result = await tool.call({ key: 'staged' } as any, { ...baseContext, session });

    expect(pagesRepository.findPageByKey).not.toHaveBeenCalled();
    expect(wikiService.readPage).toHaveBeenCalledWith('GLOBAL', null, 'staged');
    expect(wikiService.deletePage).toHaveBeenCalledTimes(1);
    expect(result.structured).toEqual({ success: true, key: 'staged' });
  });

  it('returns a friendly message when the page does not exist', async () => {
    const wikiService = { deletePage: vi.fn(), deleteFromIndex: vi.fn() };
    const pagesRepository = { findPageByKey: vi.fn().mockResolvedValue(null) };
    const knowledgeRepository = { createEvent: vi.fn() };
    const tool = new WikiRemoveTool(wikiService as any, pagesRepository as any, knowledgeRepository as any);
    const result = await tool.call({ key: 'missing' } as any, baseContext);
    expect(result.structured.success).toBe(false);
    expect(result.markdown).toMatch(/not found/i);
  });
});
