import { describe, it, expect } from 'vitest';
import { matchPattern, matchRules, parseCommand, generateAskPattern } from '../../../src/permission/wildcard.js';

describe('matchPattern - 通配符模式匹配', () => {
  describe('* 通配符', () => {
    it('匹配任意字符', () => {
      expect(matchPattern('git diff', 'git diff*')).toBe(true);
      expect(matchPattern('git diff --staged', 'git diff*')).toBe(true);
      expect(matchPattern('git diff HEAD~1', 'git diff*')).toBe(true);
    });

    it('不匹配不同前缀', () => {
      expect(matchPattern('git status', 'git diff*')).toBe(false);
      expect(matchPattern('git pull', 'git diff*')).toBe(false);
    });

    it('匹配危险命令模式 rm -rf*', () => {
      expect(matchPattern('rm -rf /', 'rm -rf*')).toBe(true);
      expect(matchPattern('rm -rf /home', 'rm -rf*')).toBe(true);
      expect(matchPattern('rm -rf .', 'rm -rf*')).toBe(true);
    });

    it('rm 普通命令不匹配 rm -rf*', () => {
      expect(matchPattern('rm file.txt', 'rm -rf*')).toBe(false);
      expect(matchPattern('rm -r dir', 'rm -rf*')).toBe(false);
    });

    it('中间位置的通配符', () => {
      expect(matchPattern('git push origin main', 'git push * main')).toBe(true);
      expect(matchPattern('git push upstream main', 'git push * main')).toBe(true);
    });

    it('多个通配符', () => {
      expect(matchPattern('git push origin main', 'git * origin *')).toBe(true);
      expect(matchPattern('git pull origin main', 'git * origin *')).toBe(true);
    });
  });

  describe('? 通配符', () => {
    it('匹配单个字符', () => {
      expect(matchPattern('ls -a', 'ls -?')).toBe(true);
      expect(matchPattern('ls -l', 'ls -?')).toBe(true);
    });

    it('不匹配多个字符', () => {
      expect(matchPattern('ls -la', 'ls -?')).toBe(false);
    });
  });

  describe('精确匹配', () => {
    it('完全相同的字符串', () => {
      expect(matchPattern('ls', 'ls')).toBe(true);
      expect(matchPattern('pwd', 'pwd')).toBe(true);
    });

    it('不匹配带参数的命令', () => {
      expect(matchPattern('ls -la', 'ls')).toBe(false);
      expect(matchPattern('pwd /home', 'pwd')).toBe(false);
    });
  });

  describe('大小写不敏感', () => {
    it('匹配不同大小写', () => {
      expect(matchPattern('GIT DIFF', 'git diff*')).toBe(true);
      expect(matchPattern('Git Diff', 'git diff*')).toBe(true);
    });
  });

  describe('特殊字符转义', () => {
    it('正确处理点号', () => {
      expect(matchPattern('file.txt', 'file.txt')).toBe(true);
      expect(matchPattern('fileatxt', 'file.txt')).toBe(false);
    });

    it('正确处理括号', () => {
      expect(matchPattern('echo (test)', 'echo (test)')).toBe(true);
    });
  });
});

describe('matchRules - 规则匹配', () => {
  const rules = [
    { pattern: 'ls *', action: 'allow' as const },
    { pattern: 'rm -rf*', action: 'deny' as const },
    { pattern: 'git *', action: 'ask' as const },
  ];

  it('匹配 allow 规则', () => {
    const result = matchRules('ls -la', rules, 'ask');
    expect(result.action).toBe('allow');
  });

  it('匹配 deny 规则', () => {
    const result = matchRules('rm -rf /', rules, 'ask');
    expect(result.action).toBe('deny');
  });

  it('匹配 ask 规则', () => {
    const result = matchRules('git push', rules, 'deny');
    expect(result.action).toBe('ask');
  });

  it('无匹配时返回默认动作', () => {
    const result = matchRules('npm install', rules, 'ask');
    expect(result.action).toBe('ask');
  });

  it('返回匹配的模式', () => {
    const result = matchRules('rm -rf /home', rules, 'ask');
    expect(result.matchedPattern).toBe('rm -rf*');
  });

  it('空规则列表返回默认动作', () => {
    const result = matchRules('any command', [], 'allow');
    expect(result.action).toBe('allow');
  });
});

describe('parseCommand - 命令解析', () => {
  it('解析简单命令', () => {
    const result = parseCommand('ls');
    expect(result.head).toBe('ls');
    expect(result.sub).toBeUndefined();
  });

  it('解析带子命令的命令', () => {
    const result = parseCommand('git push');
    expect(result.head).toBe('git');
    expect(result.sub).toBe('push');
  });

  it('解析带参数的命令', () => {
    const result = parseCommand('git push origin main');
    expect(result.head).toBe('git');
    expect(result.sub).toBe('push');
    expect(result.args).toContain('origin');
    expect(result.args).toContain('main');
  });
});

describe('generateAskPattern - 生成询问模式', () => {
  it('简单命令生成 cmd *', () => {
    const pattern = generateAskPattern('ls -la');
    expect(pattern).toBe('ls *');
  });

  it('带子命令生成 cmd sub *', () => {
    const pattern = generateAskPattern('git push origin');
    expect(pattern).toBe('git push *');
  });

  it('npm install 生成 npm install *', () => {
    const pattern = generateAskPattern('npm install lodash');
    expect(pattern).toBe('npm install *');
  });
});
