import { parseArgs, isDeploymentAdapter, isBuildTarget } from '../args';

describe('parseArgs', () => {
  describe('positional arguments', () => {
    it('should collect positional args in _ array', () => {
      const result = parseArgs(['create', 'my-project']);
      expect(result._).toEqual(['create', 'my-project']);
    });

    it('should return empty _ array when no positional args', () => {
      const result = parseArgs(['--help']);
      expect(result._).toEqual([]);
    });
  });

  describe('--yes / -y flag', () => {
    it('should parse --yes flag', () => {
      const result = parseArgs(['create', 'my-project', '--yes']);
      expect(result.yes).toBe(true);
    });

    it('should parse -y short flag', () => {
      const result = parseArgs(['create', 'my-project', '-y']);
      expect(result.yes).toBe(true);
    });

    it('should not set yes when flag is absent', () => {
      const result = parseArgs(['create', 'my-project']);
      expect(result.yes).toBeUndefined();
    });
  });

  describe('--target flag', () => {
    it('should parse --target with node value', () => {
      const result = parseArgs(['create', '--target', 'node']);
      expect(result.target).toBe('node');
    });

    it('should parse --target with vercel value', () => {
      const result = parseArgs(['create', '--target', 'vercel']);
      expect(result.target).toBe('vercel');
    });

    it('should parse --target with lambda value', () => {
      const result = parseArgs(['create', '--target', 'lambda']);
      expect(result.target).toBe('lambda');
    });

    it('should parse --target with cloudflare value', () => {
      const result = parseArgs(['create', '--target', 'cloudflare']);
      expect(result.target).toBe('cloudflare');
    });

    it('should set both target and buildTarget for values in both unions', () => {
      const result = parseArgs(['build', '--target', 'node']);
      expect(result.target).toBe('node');
      expect(result.buildTarget).toBe('node');
    });

    it('should set only buildTarget for build-only targets like sdk', () => {
      const result = parseArgs(['build', '--target', 'sdk']);
      expect(result.target).toBeUndefined();
      expect(result.buildTarget).toBe('sdk');
    });

    it('should set both for values in both unions like vercel', () => {
      const result = parseArgs(['create', '--target', 'vercel']);
      expect(result.target).toBe('vercel');
      expect(result.buildTarget).toBe('vercel');
    });

    it('should set neither for unrecognized target values', () => {
      const result = parseArgs(['build', '--target', 'unknown']);
      expect(result.target).toBeUndefined();
      expect(result.buildTarget).toBeUndefined();
    });
  });

  describe('--redis flag', () => {
    it('should parse --redis with docker value', () => {
      const result = parseArgs(['create', '--redis', 'docker']);
      expect(result.redis).toBe('docker');
    });

    it('should parse --redis with existing value', () => {
      const result = parseArgs(['create', '--redis', 'existing']);
      expect(result.redis).toBe('existing');
    });

    it('should parse --redis with none value', () => {
      const result = parseArgs(['create', '--redis', 'none']);
      expect(result.redis).toBe('none');
    });
  });

  describe('--pm flag', () => {
    it('should parse --pm with npm value', () => {
      const result = parseArgs(['create', '--pm', 'npm']);
      expect(result.pm).toBe('npm');
    });

    it('should parse --pm with yarn value', () => {
      const result = parseArgs(['create', '--pm', 'yarn']);
      expect(result.pm).toBe('yarn');
    });

    it('should parse --pm with pnpm value', () => {
      const result = parseArgs(['create', '--pm', 'pnpm']);
      expect(result.pm).toBe('pnpm');
    });

    it('should not set pm when flag is absent', () => {
      const result = parseArgs(['create']);
      expect(result.pm).toBeUndefined();
    });
  });

  describe('--cicd / --no-cicd flags', () => {
    it('should parse --cicd flag as true', () => {
      const result = parseArgs(['create', '--cicd']);
      expect(result.cicd).toBe(true);
    });

    it('should parse --no-cicd flag as false', () => {
      const result = parseArgs(['create', '--no-cicd']);
      expect(result.cicd).toBe(false);
    });

    it('should not set cicd when flag is absent', () => {
      const result = parseArgs(['create']);
      expect(result.cicd).toBeUndefined();
    });
  });

  describe('--help / -h flag', () => {
    it('should parse --help flag', () => {
      const result = parseArgs(['--help']);
      expect(result.help).toBe(true);
    });

    it('should parse -h short flag', () => {
      const result = parseArgs(['-h']);
      expect(result.help).toBe(true);
    });
  });

  describe('--out-dir / -o flag', () => {
    it('should parse --out-dir with value', () => {
      const result = parseArgs(['build', '--out-dir', 'dist/custom']);
      expect(result.outDir).toBe('dist/custom');
    });

    it('should parse -o short flag with value', () => {
      const result = parseArgs(['build', '-o', 'dist/custom']);
      expect(result.outDir).toBe('dist/custom');
    });
  });

  describe('--entry / -e flag', () => {
    it('should parse --entry with value', () => {
      const result = parseArgs(['build', '--entry', 'src/server.ts']);
      expect(result.entry).toBe('src/server.ts');
    });

    it('should parse -e short flag with value', () => {
      const result = parseArgs(['build', '-e', 'src/server.ts']);
      expect(result.entry).toBe('src/server.ts');
    });
  });

  describe('--verbose / -v flag', () => {
    it('should parse --verbose flag', () => {
      const result = parseArgs(['dev', '--verbose']);
      expect(result.verbose).toBe(true);
    });

    it('should parse -v short flag', () => {
      const result = parseArgs(['dev', '-v']);
      expect(result.verbose).toBe(true);
    });
  });

  describe('--watch / -w flag', () => {
    it('should parse --watch flag', () => {
      const result = parseArgs(['test', '--watch']);
      expect(result.watch).toBe(true);
    });

    it('should parse -w short flag', () => {
      const result = parseArgs(['test', '-w']);
      expect(result.watch).toBe(true);
    });
  });

  describe('--timeout / -t flag', () => {
    it('should parse --timeout with numeric value', () => {
      const result = parseArgs(['test', '--timeout', '5000']);
      expect(result.timeout).toBe(5000);
    });

    it('should parse -t short flag with numeric value', () => {
      const result = parseArgs(['test', '-t', '10000']);
      expect(result.timeout).toBe(10000);
    });

    it('should return undefined for non-numeric timeout', () => {
      const result = parseArgs(['test', '--timeout', 'invalid']);
      expect(result.timeout).toBeUndefined();
    });
  });

  describe('--runInBand / -i flag', () => {
    it('should parse --runInBand flag', () => {
      const result = parseArgs(['test', '--runInBand']);
      expect(result.runInBand).toBe(true);
    });

    it('should parse -i short flag', () => {
      const result = parseArgs(['test', '-i']);
      expect(result.runInBand).toBe(true);
    });
  });

  describe('--coverage / -c flag', () => {
    it('should parse --coverage flag', () => {
      const result = parseArgs(['test', '--coverage']);
      expect(result.coverage).toBe(true);
    });

    it('should parse -c short flag', () => {
      const result = parseArgs(['test', '-c']);
      expect(result.coverage).toBe(true);
    });

    it('should not set coverage when flag is absent', () => {
      const result = parseArgs(['test']);
      expect(result.coverage).toBeUndefined();
    });
  });

  describe('combined flags', () => {
    it('should parse multiple flags together', () => {
      const result = parseArgs(['create', 'my-project', '--yes', '--target', 'vercel', '--cicd']);

      expect(result._).toEqual(['create', 'my-project']);
      expect(result.yes).toBe(true);
      expect(result.target).toBe('vercel');
      expect(result.cicd).toBe(true);
    });

    it('should parse create command with all flags', () => {
      const result = parseArgs(['create', 'my-app', '-y', '--target', 'node', '--redis', 'docker', '--cicd']);

      expect(result._).toEqual(['create', 'my-app']);
      expect(result.yes).toBe(true);
      expect(result.target).toBe('node');
      expect(result.redis).toBe('docker');
      expect(result.cicd).toBe(true);
    });

    it('should parse test command with all flags', () => {
      const result = parseArgs(['test', '--runInBand', '--watch', '--verbose', '--coverage', '--timeout', '30000']);

      expect(result._).toEqual(['test']);
      expect(result.runInBand).toBe(true);
      expect(result.watch).toBe(true);
      expect(result.verbose).toBe(true);
      expect(result.coverage).toBe(true);
      expect(result.timeout).toBe(30000);
    });
  });
});

describe('isDeploymentAdapter', () => {
  it('should return true for valid deployment adapters', () => {
    expect(isDeploymentAdapter('node')).toBe(true);
    expect(isDeploymentAdapter('vercel')).toBe(true);
    expect(isDeploymentAdapter('lambda')).toBe(true);
    expect(isDeploymentAdapter('cloudflare')).toBe(true);
  });

  it('should return false for non-adapter values', () => {
    expect(isDeploymentAdapter('cli')).toBe(false);
    expect(isDeploymentAdapter('sdk')).toBe(false);
    expect(isDeploymentAdapter('unknown')).toBe(false);
  });
});

describe('isBuildTarget', () => {
  it('should return true for valid build targets', () => {
    expect(isBuildTarget('cli')).toBe(true);
    expect(isBuildTarget('node')).toBe(true);
    expect(isBuildTarget('vercel')).toBe(true);
    expect(isBuildTarget('lambda')).toBe(true);
    expect(isBuildTarget('cloudflare')).toBe(true);
    expect(isBuildTarget('sdk')).toBe(true);
    expect(isBuildTarget('browser')).toBe(true);
  });

  it('should return false for non-target values', () => {
    expect(isBuildTarget('unknown')).toBe(false);
    expect(isBuildTarget('docker')).toBe(false);
  });
});
