import { expect, test, describe } from 'bun:test';
import {
  isCcsWebSearchHook,
  deduplicateCcsHooks,
} from '../../../../src/utils/websearch/hook-utils';

describe('isCcsWebSearchHook', () => {
  test('Returns true for CCS hook with forward slashes (Unix path)', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(true);
  });

  test('Returns true for CCS hook with backslashes (Windows path)', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node C:\\Users\\user\\.ccs\\hooks\\websearch-transformer\\index.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(true);
  });

  test('Returns true for mixed path separators', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /home/user\\.ccs/hooks\\websearch-transformer/index.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(true);
  });

  test('Returns true for path with double slashes (normalization)', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /home/user//.ccs//hooks/websearch-transformer/index.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(true);
  });

  test('Returns false for non-WebSearch matcher', () => {
    const hook = {
      matcher: 'SomethingElse',
      hooks: [
        {
          command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });

  test('Returns false for WebSearch with non-CCS hook command', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /some/other/path/custom-hook.js',
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });

  test('Returns false when hooks array is missing', () => {
    const hook = {
      matcher: 'WebSearch',
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });

  test('Returns false when hooks array is empty', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [],
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });

  test('Returns false when command is missing', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [{}],
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });

  test('Returns false when command is not a string', () => {
    const hook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 123,
        },
      ],
    };
    expect(isCcsWebSearchHook(hook)).toBe(false);
  });
});

describe('deduplicateCcsHooks', () => {
  test('No-op when 0 CCS hooks (returns false)', () => {
    const settings = {
      hooks: {
        PreToolUse: [
          {
            matcher: 'SomeOtherMatcher',
            hooks: [{ command: 'other-command' }],
          },
        ],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(false);
    expect(settings.hooks.PreToolUse).toHaveLength(1);
  });

  test('No-op when 1 CCS hook (returns false)', () => {
    const settings = {
      hooks: {
        PreToolUse: [
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
        ],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(false);
    expect(settings.hooks.PreToolUse).toHaveLength(1);
  });

  test('Removes duplicates when 2+ CCS hooks (returns true, keeps first)', () => {
    const settings = {
      hooks: {
        PreToolUse: [
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node C:\\Users\\user\\.ccs\\hooks\\websearch-transformer\\index.js',
              },
            ],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /another/path/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
        ],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(true);
    expect(settings.hooks.PreToolUse).toHaveLength(1);
    expect(settings.hooks.PreToolUse[0]).toEqual({
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
        },
      ],
    });
  });

  test('Preserves non-CCS hooks in array', () => {
    const nonCcsHook = {
      matcher: 'SomeOtherMatcher',
      hooks: [{ command: 'other-command' }],
    };
    const settings = {
      hooks: {
        PreToolUse: [
          nonCcsHook,
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node C:\\Users\\user\\.ccs\\hooks\\websearch-transformer\\index.js',
              },
            ],
          },
        ],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(true);
    expect(settings.hooks.PreToolUse).toHaveLength(2);
    expect(settings.hooks.PreToolUse[0]).toEqual(nonCcsHook);
  });

  test('Returns false when hooks is undefined', () => {
    const settings = {};
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(false);
  });

  test('Returns false when PreToolUse is undefined', () => {
    const settings = {
      hooks: {},
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(false);
  });

  test('Handles multiple non-CCS hooks with duplicates', () => {
    const settings = {
      hooks: {
        PreToolUse: [
          {
            matcher: 'OtherMatcher1',
            hooks: [{ command: 'command1' }],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /path1/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
          {
            matcher: 'OtherMatcher2',
            hooks: [{ command: 'command2' }],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /path2/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
        ],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(true);
    expect(settings.hooks.PreToolUse).toHaveLength(3);
    // First and third should be non-CCS hooks, second should be the first CCS hook
    expect(settings.hooks.PreToolUse[0].matcher).toBe('OtherMatcher1');
    expect(settings.hooks.PreToolUse[1].matcher).toBe('WebSearch');
    expect(settings.hooks.PreToolUse[2].matcher).toBe('OtherMatcher2');
  });

  test('Edge case: Empty PreToolUse array', () => {
    const settings = {
      hooks: {
        PreToolUse: [],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(false);
    expect(settings.hooks.PreToolUse).toHaveLength(0);
  });

  test('Stress test: 15 duplicate CCS WebSearch hooks', () => {
    const ccsHook = {
      matcher: 'WebSearch',
      hooks: [
        {
          command: 'node /home/user/.ccs/hooks/websearch-transformer/index.js',
        },
      ],
    };
    const settings = {
      hooks: {
        PreToolUse: Array(15).fill(ccsHook),
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(true);
    expect(settings.hooks.PreToolUse).toHaveLength(1);
    expect(settings.hooks.PreToolUse[0]).toEqual(ccsHook);
  });

  test('Leaves PostToolUse and PreToolCall untouched', () => {
    const postToolUseHook1 = {
      matcher: 'CustomMatcher1',
      hooks: [{ command: 'custom-command-1' }],
    };
    const postToolUseHook2 = {
      matcher: 'CustomMatcher2',
      hooks: [{ command: 'custom-command-2' }],
    };
    const preToolCallHook = {
      matcher: 'CustomMatcher3',
      hooks: [{ command: 'custom-command-3' }],
    };
    const settings = {
      hooks: {
        PreToolUse: [
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /path1/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /path2/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
          {
            matcher: 'WebSearch',
            hooks: [
              {
                command: 'node /path3/.ccs/hooks/websearch-transformer/index.js',
              },
            ],
          },
        ],
        PostToolUse: [postToolUseHook1, postToolUseHook2],
        PreToolCall: [preToolCallHook],
      },
    };
    const result = deduplicateCcsHooks(settings);
    expect(result).toBe(true);
    // PreToolUse should be deduplicated to 1 hook
    expect(settings.hooks.PreToolUse).toHaveLength(1);
    expect(settings.hooks.PreToolUse[0].matcher).toBe('WebSearch');
    // PostToolUse should remain unchanged with 2 hooks
    expect(settings.hooks.PostToolUse).toHaveLength(2);
    expect(settings.hooks.PostToolUse[0]).toEqual(postToolUseHook1);
    expect(settings.hooks.PostToolUse[1]).toEqual(postToolUseHook2);
    // PreToolCall should remain unchanged with 1 hook
    expect(settings.hooks.PreToolCall).toHaveLength(1);
    expect(settings.hooks.PreToolCall[0]).toEqual(preToolCallHook);
  });
});
