import { join } from 'path'
import { existsSync, mkdirSync, rmSync } from 'fs'
import { tmpdir } from 'os'
import * as fc from 'fast-check'

// Minimal ConfigStore interface for testing
interface IConfigStore {
  getBasePath(): string
  getTempPath(): string
  get(key: string): any
  set(key: string, value: any): void
}

// Mock ConfigStore for testing
class MockConfigStore implements IConfigStore {
  private mockBasePath: string
  private config: Record<string, any> = {}

  constructor() {
    // Create a temporary directory for testing
    const testDir = join(tmpdir(), 'phper-test-' + Date.now())
    mkdirSync(testDir, { recursive: true })
    
    this.mockBasePath = testDir
    this.config = {
      goVersions: [],
      activeGoVersion: ''
    }
  }

  getBasePath(): string {
    return this.mockBasePath
  }

  getTempPath(): string {
    return join(this.mockBasePath, 'temp')
  }

  get(key: string): any {
    return this.config[key]
  }

  set(key: string, value: any): void {
    this.config[key] = value
  }

  cleanup(): void {
    if (existsSync(this.mockBasePath)) {
      rmSync(this.mockBasePath, { recursive: true, force: true })
    }
  }
}

// Simplified GoManager for testing (without external dependencies)
class TestGoManager {
  private configStore: IConfigStore

  constructor(configStore: IConfigStore) {
    this.configStore = configStore
  }

  getGoBasePath(): string {
    return join(this.configStore.getBasePath(), 'go')
  }

  getGoPath(version: string): string {
    return join(this.getGoBasePath(), `go-${version}`)
  }

  getDefaultGoPath(): string {
    return join(this.getGoBasePath(), 'workspace')
  }

  async getInstalledVersions(): Promise<any[]> {
    const goBasePath = this.getGoBasePath()
    
    if (!existsSync(goBasePath)) {
      return []
    }

    // In a real implementation, this would scan directories
    // For testing, just return empty array
    return []
  }

  async validateInstallation(version: string): Promise<boolean> {
    const goPath = this.getGoPath(version)
    const goExe = join(goPath, 'bin', 'go.exe')
    
    return existsSync(goExe)
  }

  // Method to test API response parsing
  parseApiResponse(releases: any[]): any[] {
    const availableVersions: any[] = []

    for (const release of releases) {
      if (release.stable) {
        const windowsFile = release.files?.find((f: any) => 
          f.os === 'windows' && f.arch === 'amd64' && f.kind === 'archive'
        )
        
        if (windowsFile) {
          availableVersions.push({
            version: release.version,
            stable: release.stable,
            downloadUrl: `https://golang.org/dl/${windowsFile.filename}`,
            size: windowsFile.size,
            sha256: windowsFile.sha256
          })
        }
      }
    }

    return availableVersions.slice(0, 20)
  }
}

// Simple test runner for Node.js environment
async function runTests() {
  console.log('Running GoManager tests...')
  
  // Basic test implementation without external framework
  const tests = [
    {
      name: 'GoManager initialization',
      test: () => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        console.assert(manager instanceof TestGoManager, 'GoManager should initialize correctly')
        mockStore.cleanup()
        return true
      }
    },
    {
      name: 'Path generation',
      test: () => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        const basePath = manager.getGoBasePath()
        const versionPath = manager.getGoPath('go1.21.5')
        const goPath = manager.getDefaultGoPath()
        
        console.assert(basePath.includes('go'), 'Base path should contain go directory')
        console.assert(versionPath.includes('go-go1.21.5'), 'Version path should contain version')
        console.assert(goPath.includes('workspace'), 'GOPATH should contain workspace')
        
        mockStore.cleanup()
        return true
      }
    },
    {
      name: 'Empty versions list',
      test: async () => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        const versions = await manager.getInstalledVersions()
        
        console.assert(Array.isArray(versions), 'Should return array')
        console.assert(versions.length === 0, 'Should return empty array for no installations')
        
        mockStore.cleanup()
        return true
      }
    },
    {
      name: 'Configuration integration',
      test: () => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        
        // Test config store integration
        const activeVersion = mockStore.get('activeGoVersion')
        const goVersions = mockStore.get('goVersions')
        
        console.assert(typeof activeVersion === 'string', 'Active version should be string')
        console.assert(Array.isArray(goVersions), 'Go versions should be array')
        
        mockStore.cleanup()
        return true
      }
    },
    {
      name: 'Installation validation',
      test: async () => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        
        // Test validation for non-existent version
        const isValid = await manager.validateInstallation('go1.99.99')
        console.assert(isValid === false, 'Should return false for non-existent version')
        
        mockStore.cleanup()
        return true
      }
    }
  ]
  
  let passed = 0
  let failed = 0
  
  for (const test of tests) {
    try {
      const result = await test.test()
      if (result) {
        console.log(`✓ ${test.name}`)
        passed++
      } else {
        console.log(`✗ ${test.name}`)
        failed++
      }
    } catch (error) {
      console.log(`✗ ${test.name}: ${error}`)
      failed++
    }
  }
  
  console.log(`\nTests completed: ${passed} passed, ${failed} failed`)
  return failed === 0
}
// Run tests if this file is executed directly
if (require.main === module) {
  runTests().then(success => {
    process.exit(success ? 0 : 1)
  }).catch(error => {
    console.error('Test execution failed:', error)
    process.exit(1)
  })
}

// Export for potential use in other test files
export { TestGoManager, MockConfigStore }

// Property-based tests using Jest and fast-check
describe('Go Version Management Properties', () => {
  test('Property 1: API Version Fetching Consistency', () => {
    // **Feature: go-version-management, Property 1: API Version Fetching Consistency**
    fc.assert(fc.property(
      fc.array(fc.record({
        version: fc.string({ minLength: 1 }),
        stable: fc.boolean(),
        files: fc.array(fc.record({
          os: fc.constantFrom('windows', 'linux', 'darwin'),
          arch: fc.constantFrom('amd64', '386', 'arm64'),
          kind: fc.constantFrom('archive', 'installer', 'source'),
          filename: fc.string({ minLength: 1 }),
          size: fc.nat(),
          sha256: fc.string({ minLength: 64, maxLength: 64 }).filter(s => /^[0-9a-f]+$/i.test(s))
        }))
      })),
      (mockApiResponse) => {
        const mockStore = new MockConfigStore()
        const manager = new TestGoManager(mockStore)
        
        try {
          const result = manager.parseApiResponse(mockApiResponse)
          
          // Verify all returned versions have required fields
          result.forEach(version => {
            expect(version).toHaveProperty('version')
            expect(version).toHaveProperty('stable')
            expect(version).toHaveProperty('downloadUrl')
            expect(version).toHaveProperty('size')
            expect(version).toHaveProperty('sha256')
            
            // Verify types
            expect(typeof version.version).toBe('string')
            expect(typeof version.stable).toBe('boolean')
            expect(typeof version.downloadUrl).toBe('string')
            expect(typeof version.size).toBe('number')
            expect(typeof version.sha256).toBe('string')
            
            // Verify download URL format
            expect(version.downloadUrl).toMatch(/^https:\/\/golang\.org\/dl\//)
          })
          
          // Verify only stable versions are returned
          result.forEach(version => {
            expect(version.stable).toBe(true)
          })
          
          // Verify result is limited to 20 versions
          expect(result.length).toBeLessThanOrEqual(20)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 10 })
  })

  test('Property 2: Download URL Construction', () => {
    // **Feature: go-version-management, Property 2: Download URL Construction**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        filename: fc.string({ minLength: 1 }).filter(f => f.endsWith('.zip')),
        size: fc.nat({ min: 1 }),
        sha256: fc.string({ minLength: 64, maxLength: 64 }).filter(s => /^[0-9a-f]+$/i.test(s))
      }),
      (goVersion) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate constructing download URL
          const downloadUrl = `https://golang.org/dl/${goVersion.filename}`
          
          // Verify URL construction
          expect(downloadUrl).toMatch(/^https:\/\/golang\.org\/dl\//)
          expect(downloadUrl).toContain(goVersion.filename)
          expect(downloadUrl).toMatch(/\.zip$/)
          
          // Verify the URL is well-formed
          expect(() => new URL(downloadUrl)).not.toThrow()
          
          // Verify version information is preserved
          expect(goVersion.version).toMatch(/^go\d+\.\d+\.\d+$/)
          expect(goVersion.size).toBeGreaterThan(0)
          expect(goVersion.sha256).toMatch(/^[0-9a-f]{64}$/i)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 3: Download Progress Reporting', () => {
    // **Feature: go-version-management, Property 3: Download Progress Reporting**
    fc.assert(fc.property(
      fc.record({
        downloadedBytes: fc.nat(),
        totalBytes: fc.nat({ min: 1 }),
        percent: fc.integer({ min: 0, max: 100 })
      }).filter(progress => progress.downloadedBytes <= progress.totalBytes),
      (progressData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate progress reporting structure
          const progress = {
            percent: progressData.percent,
            downloadedBytes: progressData.downloadedBytes,
            totalBytes: progressData.totalBytes,
            speed: progressData.downloadedBytes > 0 ? progressData.downloadedBytes / 1000 : 0
          }
          
          // Verify progress data structure
          expect(progress).toHaveProperty('percent')
          expect(progress).toHaveProperty('downloadedBytes')
          expect(progress).toHaveProperty('totalBytes')
          expect(progress).toHaveProperty('speed')
          
          // Verify data types
          expect(typeof progress.percent).toBe('number')
          expect(typeof progress.downloadedBytes).toBe('number')
          expect(typeof progress.totalBytes).toBe('number')
          expect(typeof progress.speed).toBe('number')
          
          // Verify value ranges
          expect(progress.percent).toBeGreaterThanOrEqual(0)
          expect(progress.percent).toBeLessThanOrEqual(100)
          expect(progress.downloadedBytes).toBeGreaterThanOrEqual(0)
          expect(progress.totalBytes).toBeGreaterThan(0)
          expect(progress.downloadedBytes).toBeLessThanOrEqual(progress.totalBytes)
          expect(progress.speed).toBeGreaterThanOrEqual(0)
          
          // Verify percentage calculation consistency
          if (progress.totalBytes > 0) {
            const calculatedPercent = Math.round((progress.downloadedBytes / progress.totalBytes) * 100)
            // Allow some tolerance for rounding differences
            expect(Math.abs(progress.percent - calculatedPercent)).toBeLessThanOrEqual(1)
          }
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 4: Installation Validation Completeness', () => {
    // **Feature: go-version-management, Property 4: Installation Validation Completeness**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        hasGoExe: fc.boolean(),
        hasGofmtExe: fc.boolean(),
        hasValidVersion: fc.boolean(),
        hasSrcDir: fc.boolean()
      }),
      (installationData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate installation validation components
          const validationChecks = {
            goExeExists: installationData.hasGoExe,
            gofmtExeExists: installationData.hasGofmtExe,
            versionMatches: installationData.hasValidVersion,
            srcDirExists: installationData.hasSrcDir
          }
          
          // For a complete installation, all checks should pass
          const isCompleteInstallation = Object.values(validationChecks).every(check => check === true)
          
          // Verify validation structure
          expect(validationChecks).toHaveProperty('goExeExists')
          expect(validationChecks).toHaveProperty('gofmtExeExists')
          expect(validationChecks).toHaveProperty('versionMatches')
          expect(validationChecks).toHaveProperty('srcDirExists')
          
          // Verify types
          expect(typeof validationChecks.goExeExists).toBe('boolean')
          expect(typeof validationChecks.gofmtExeExists).toBe('boolean')
          expect(typeof validationChecks.versionMatches).toBe('boolean')
          expect(typeof validationChecks.srcDirExists).toBe('boolean')
          
          // Verify version format
          expect(installationData.version).toMatch(/^go\d+\.\d+\.\d+$/)
          
          // If installation is complete, all validation checks should pass
          if (isCompleteInstallation) {
            expect(validationChecks.goExeExists).toBe(true)
            expect(validationChecks.gofmtExeExists).toBe(true)
            expect(validationChecks.versionMatches).toBe(true)
            expect(validationChecks.srcDirExists).toBe(true)
          }
          
          // If any critical component is missing, installation should be considered incomplete
          if (!validationChecks.goExeExists || !validationChecks.gofmtExeExists) {
            expect(isCompleteInstallation).toBe(false)
          }
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 5: Duplicate Installation Prevention', () => {
    // **Feature: go-version-management, Property 5: Duplicate Installation Prevention**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        isAlreadyInstalled: fc.boolean(),
        installationAttempts: fc.integer({ min: 1, max: 5 })
      }),
      (installationData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate installation state
          const installedVersions = installationData.isAlreadyInstalled 
            ? [installationData.version] 
            : []
          
          // Simulate multiple installation attempts
          const installationResults = []
          for (let i = 0; i < installationData.installationAttempts; i++) {
            const isVersionInstalled = installedVersions.includes(installationData.version)
            const result = {
              success: !isVersionInstalled,
              message: isVersionInstalled 
                ? `Go ${installationData.version} 已安装，无需重复安装`
                : `Go ${installationData.version} 安装成功`,
              attempt: i + 1
            }
            installationResults.push(result)
            
            // If installation was successful, add to installed versions
            if (result.success) {
              installedVersions.push(installationData.version)
            }
          }
          
          // Verify installation results structure
          installationResults.forEach(result => {
            expect(result).toHaveProperty('success')
            expect(result).toHaveProperty('message')
            expect(result).toHaveProperty('attempt')
            
            expect(typeof result.success).toBe('boolean')
            expect(typeof result.message).toBe('string')
            expect(typeof result.attempt).toBe('number')
            expect(result.message.length).toBeGreaterThan(0)
          })
          
          // Verify duplicate installation prevention
          if (installationData.isAlreadyInstalled) {
            // If version was already installed, all attempts should fail
            installationResults.forEach(result => {
              expect(result.success).toBe(false)
              expect(result.message).toContain('已安装')
            })
          } else {
            // If version wasn't installed, first attempt should succeed, rest should fail
            expect(installationResults[0].success).toBe(true)
            expect(installationResults[0].message).toContain('安装成功')
            
            // Subsequent attempts should fail due to duplicate prevention
            for (let i = 1; i < installationResults.length; i++) {
              expect(installationResults[i].success).toBe(false)
              expect(installationResults[i].message).toContain('已安装')
            }
          }
          
          // Verify version should only appear once in installed versions list
          const versionCount = installedVersions.filter(v => v === installationData.version).length
          expect(versionCount).toBeLessThanOrEqual(1)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 11: Environment Variable Validation', () => {
    // **Feature: go-version-management, Property 11: Environment Variable Validation**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        goroot: fc.string({ minLength: 1 }),
        gopath: fc.string({ minLength: 1 }),
        goBin: fc.string({ minLength: 1 }),
        systemGoVersionOutput: fc.string({ minLength: 1 }),
        systemGoRootOutput: fc.string({ minLength: 1 })
      }),
      (validationData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate environment variable validation after version switch
          const expectedGoRoot = validationData.goroot
          const expectedGoPath = validationData.gopath
          const expectedGoBin = validationData.goBin
          
          // Simulate system command outputs
          const goVersionMatches = validationData.systemGoVersionOutput.includes(validationData.version)
          const goRootMatches = validationData.systemGoRootOutput.trim() === expectedGoRoot
          
          // Simulate validation results
          const validationResult = {
            environmentVariables: {
              GOROOT: expectedGoRoot,
              GOPATH: expectedGoPath,
              PATH: `${expectedGoBin};C:\\Windows\\System32`
            },
            systemValidation: {
              goVersionOutput: validationData.systemGoVersionOutput,
              goRootOutput: validationData.systemGoRootOutput,
              goVersionMatches,
              goRootMatches
            },
            errors: [] as string[]
          }
          
          // Perform validation checks
          if (!goVersionMatches) {
            validationResult.errors.push(`go version 输出不匹配: 期望包含 '${validationData.version}', 实际 '${validationData.systemGoVersionOutput}'`)
          }
          
          if (!goRootMatches) {
            validationResult.errors.push(`GOROOT 不匹配: 期望 '${expectedGoRoot}', 实际 '${validationData.systemGoRootOutput.trim()}'`)
          }
          
          // Check if PATH contains Go binary
          const pathContainsGoBin = validationResult.environmentVariables.PATH.includes(expectedGoBin)
          if (!pathContainsGoBin) {
            validationResult.errors.push(`PATH 中缺少 Go 二进制路径: '${expectedGoBin}'`)
          }
          
          const isValid = validationResult.errors.length === 0
          
          // Verify validation result structure
          expect(validationResult).toHaveProperty('environmentVariables')
          expect(validationResult).toHaveProperty('systemValidation')
          expect(validationResult).toHaveProperty('errors')
          
          // Verify environment variables structure
          expect(validationResult.environmentVariables).toHaveProperty('GOROOT')
          expect(validationResult.environmentVariables).toHaveProperty('GOPATH')
          expect(validationResult.environmentVariables).toHaveProperty('PATH')
          
          // Verify system validation structure
          expect(validationResult.systemValidation).toHaveProperty('goVersionOutput')
          expect(validationResult.systemValidation).toHaveProperty('goRootOutput')
          expect(validationResult.systemValidation).toHaveProperty('goVersionMatches')
          expect(validationResult.systemValidation).toHaveProperty('goRootMatches')
          
          // Verify types
          expect(typeof validationResult.environmentVariables.GOROOT).toBe('string')
          expect(typeof validationResult.environmentVariables.GOPATH).toBe('string')
          expect(typeof validationResult.environmentVariables.PATH).toBe('string')
          expect(typeof validationResult.systemValidation.goVersionMatches).toBe('boolean')
          expect(typeof validationResult.systemValidation.goRootMatches).toBe('boolean')
          expect(Array.isArray(validationResult.errors)).toBe(true)
          
          // Verify validation logic
          if (goVersionMatches && goRootMatches && pathContainsGoBin) {
            expect(isValid).toBe(true)
            expect(validationResult.errors.length).toBe(0)
          } else {
            expect(isValid).toBe(false)
            expect(validationResult.errors.length).toBeGreaterThan(0)
          }
          
          // Verify error messages are descriptive
          validationResult.errors.forEach(error => {
            expect(typeof error).toBe('string')
            expect(error.length).toBeGreaterThan(0)
            expect(error).toMatch(/期望|实际|不匹配|缺少/)
          })
          
          // Verify PATH structure
          const pathEntries = validationResult.environmentVariables.PATH.split(';')
          expect(pathEntries.length).toBeGreaterThan(0)
          if (pathContainsGoBin) {
            expect(pathEntries).toContain(expectedGoBin)
          }
          
          // Verify version format in validation
          expect(validationData.version).toMatch(/^go\d+\.\d+\.\d+$/)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 7: Active Version Environment Management', () => {
    // **Feature: go-version-management, Property 7: Active Version Environment Management**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        goroot: fc.string({ minLength: 1 }),
        gopath: fc.string({ minLength: 1 }),
        goBin: fc.string({ minLength: 1 }),
        existingPathEntries: fc.array(fc.string({ minLength: 1 })),
        hasOldGoPaths: fc.boolean()
      }),
      (envData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate environment variable update process
          const currentPath = envData.existingPathEntries.join(';')
          
          // Add some old Go paths if specified
          let pathWithOldGo = currentPath
          if (envData.hasOldGoPaths) {
            pathWithOldGo = `${currentPath};C:\\go\\go-1.20.0\\bin;C:\\go\\go-1.19.0\\bin`
          }
          
          // Simulate PATH cleaning and updating
          const pathArray = pathWithOldGo.split(';').filter(p => p.trim() !== '')
          
          // Remove old Go paths (simulate the cleaning logic)
          const filteredPaths = pathArray.filter(p => 
            !p.includes('\\go\\go-') && 
            !p.includes('\\go-') && 
            !p.includes('\\golang\\') &&
            !p.includes('\\Go\\')
          )
          
          // Add new Go path
          const newPathArray = [envData.goBin, ...filteredPaths]
          const finalPath = newPathArray.filter(p => p.trim() !== '').join(';')
          
          // Simulate environment variables
          const environmentVariables = {
            GOROOT: envData.goroot,
            GOPATH: envData.gopath,
            PATH: finalPath
          }
          
          // Verify environment variable structure
          expect(environmentVariables).toHaveProperty('GOROOT')
          expect(environmentVariables).toHaveProperty('GOPATH')
          expect(environmentVariables).toHaveProperty('PATH')
          
          // Verify types
          expect(typeof environmentVariables.GOROOT).toBe('string')
          expect(typeof environmentVariables.GOPATH).toBe('string')
          expect(typeof environmentVariables.PATH).toBe('string')
          
          // Verify values are non-empty
          expect(environmentVariables.GOROOT.length).toBeGreaterThan(0)
          expect(environmentVariables.GOPATH.length).toBeGreaterThan(0)
          expect(environmentVariables.PATH.length).toBeGreaterThan(0)
          
          // Verify PATH contains the new Go binary path
          expect(environmentVariables.PATH).toContain(envData.goBin)
          
          // Verify old Go paths are removed
          const pathEntries = environmentVariables.PATH.split(';')
          const hasOldGoPaths = pathEntries.some(p => 
            (p.includes('\\go\\go-') || p.includes('\\go-')) && p !== envData.goBin
          )
          expect(hasOldGoPaths).toBe(false)
          
          // Verify Go binary path appears only once
          const goPathCount = pathEntries.filter(p => p === envData.goBin).length
          expect(goPathCount).toBe(1)
          
          // Verify Go binary path is at the beginning (highest priority)
          expect(pathEntries[0]).toBe(envData.goBin)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 14: GOPATH Default Configuration', () => {
    // **Feature: go-version-management, Property 14: GOPATH Default Configuration**
    fc.assert(fc.property(
      fc.record({
        basePath: fc.string({ minLength: 1 }),
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v))
      }),
      (configData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate GOPATH configuration logic
          const goBasePath = `${configData.basePath}\\go`
          const defaultGoPath = `${goBasePath}\\workspace`
          
          // Simulate GOPATH workspace structure
          const workspaceStructure = {
            gopath: defaultGoPath,
            subdirectories: ['src', 'pkg', 'bin'],
            fullPaths: [
              `${defaultGoPath}\\src`,
              `${defaultGoPath}\\pkg`,
              `${defaultGoPath}\\bin`
            ]
          }
          
          // Verify GOPATH structure
          expect(workspaceStructure).toHaveProperty('gopath')
          expect(workspaceStructure).toHaveProperty('subdirectories')
          expect(workspaceStructure).toHaveProperty('fullPaths')
          
          // Verify types
          expect(typeof workspaceStructure.gopath).toBe('string')
          expect(Array.isArray(workspaceStructure.subdirectories)).toBe(true)
          expect(Array.isArray(workspaceStructure.fullPaths)).toBe(true)
          
          // Verify GOPATH format
          expect(workspaceStructure.gopath).toContain('workspace')
          expect(workspaceStructure.gopath.length).toBeGreaterThan(0)
          
          // Verify standard Go workspace subdirectories
          expect(workspaceStructure.subdirectories).toContain('src')
          expect(workspaceStructure.subdirectories).toContain('pkg')
          expect(workspaceStructure.subdirectories).toContain('bin')
          expect(workspaceStructure.subdirectories.length).toBe(3)
          
          // Verify full paths are correctly constructed
          workspaceStructure.fullPaths.forEach(path => {
            expect(path).toContain(workspaceStructure.gopath)
            expect(typeof path).toBe('string')
            expect(path.length).toBeGreaterThan(workspaceStructure.gopath.length)
          })
          
          // Verify each subdirectory has a corresponding full path
          workspaceStructure.subdirectories.forEach(subdir => {
            const expectedPath = `${workspaceStructure.gopath}\\${subdir}`
            expect(workspaceStructure.fullPaths).toContain(expectedPath)
          })
          
          // Verify GOPATH is under the Go base directory
          expect(workspaceStructure.gopath).toContain(goBasePath)
          
          // Verify GOPATH uses the standard workspace directory name
          expect(workspaceStructure.gopath.endsWith('workspace')).toBe(true)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 6: File System Cleanup on Uninstall', () => {
    // **Feature: go-version-management, Property 6: File System Cleanup on Uninstall**
    fc.assert(fc.property(
      fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        versionDir: fc.string({ minLength: 1 }),
        fileCount: fc.nat({ min: 1, max: 100 }),
        dirCount: fc.nat({ min: 1, max: 20 }),
        totalSize: fc.nat({ min: 1000, max: 1000000 }),
        uninstallSuccess: fc.boolean()
      }),
      (uninstallData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate uninstall operation and file system cleanup
          const preUninstallState = {
            versionExists: true,
            directoryPath: uninstallData.versionDir,
            fileCount: uninstallData.fileCount,
            dirCount: uninstallData.dirCount,
            totalSize: uninstallData.totalSize
          }
          
          // Simulate uninstall result
          const uninstallResult = {
            success: uninstallData.uninstallSuccess,
            message: uninstallData.uninstallSuccess 
              ? `Go ${uninstallData.version} 已成功卸载`
              : `卸载失败: 文件系统清理失败`,
            filesRemoved: uninstallData.uninstallSuccess ? uninstallData.fileCount : 0,
            dirsRemoved: uninstallData.uninstallSuccess ? uninstallData.dirCount : 0,
            bytesFreed: uninstallData.uninstallSuccess ? uninstallData.totalSize : 0
          }
          
          // Simulate post-uninstall state
          const postUninstallState = {
            versionExists: !uninstallData.uninstallSuccess,
            directoryPath: uninstallData.versionDir,
            fileCount: uninstallData.uninstallSuccess ? 0 : uninstallData.fileCount,
            dirCount: uninstallData.uninstallSuccess ? 0 : uninstallData.dirCount,
            totalSize: uninstallData.uninstallSuccess ? 0 : uninstallData.totalSize
          }
          
          // Verify uninstall result structure
          expect(uninstallResult).toHaveProperty('success')
          expect(uninstallResult).toHaveProperty('message')
          expect(uninstallResult).toHaveProperty('filesRemoved')
          expect(uninstallResult).toHaveProperty('dirsRemoved')
          expect(uninstallResult).toHaveProperty('bytesFreed')
          
          // Verify types
          expect(typeof uninstallResult.success).toBe('boolean')
          expect(typeof uninstallResult.message).toBe('string')
          expect(typeof uninstallResult.filesRemoved).toBe('number')
          expect(typeof uninstallResult.dirsRemoved).toBe('number')
          expect(typeof uninstallResult.bytesFreed).toBe('number')
          
          // Verify message is descriptive
          expect(uninstallResult.message.length).toBeGreaterThan(0)
          expect(uninstallResult.message).toContain(uninstallData.version)
          
          // Verify cleanup completeness for successful uninstall
          if (uninstallData.uninstallSuccess) {
            expect(uninstallResult.success).toBe(true)
            expect(uninstallResult.message).toContain('成功卸载')
            expect(uninstallResult.filesRemoved).toBe(preUninstallState.fileCount)
            expect(uninstallResult.dirsRemoved).toBe(preUninstallState.dirCount)
            expect(uninstallResult.bytesFreed).toBe(preUninstallState.totalSize)
            
            // Post-uninstall state should show complete cleanup
            expect(postUninstallState.versionExists).toBe(false)
            expect(postUninstallState.fileCount).toBe(0)
            expect(postUninstallState.dirCount).toBe(0)
            expect(postUninstallState.totalSize).toBe(0)
          } else {
            expect(uninstallResult.success).toBe(false)
            expect(uninstallResult.message).toContain('卸载失败')
            expect(uninstallResult.filesRemoved).toBe(0)
            expect(uninstallResult.dirsRemoved).toBe(0)
            expect(uninstallResult.bytesFreed).toBe(0)
            
            // Post-uninstall state should show no changes
            expect(postUninstallState.versionExists).toBe(true)
            expect(postUninstallState.fileCount).toBe(preUninstallState.fileCount)
            expect(postUninstallState.dirCount).toBe(preUninstallState.dirCount)
            expect(postUninstallState.totalSize).toBe(preUninstallState.totalSize)
          }
          
          // Verify numeric values are non-negative
          expect(uninstallResult.filesRemoved).toBeGreaterThanOrEqual(0)
          expect(uninstallResult.dirsRemoved).toBeGreaterThanOrEqual(0)
          expect(uninstallResult.bytesFreed).toBeGreaterThanOrEqual(0)
          
          // Verify version format
          expect(uninstallData.version).toMatch(/^go\d+\.\d+\.\d+$/)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 8: Version State Consistency', () => {
    // **Feature: go-version-management, Property 8: Version State Consistency**
    fc.assert(fc.property(
      fc.record({
        initialVersions: fc.array(fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v))),
        versionToUninstall: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        wasActiveVersion: fc.boolean(),
        uninstallSuccess: fc.boolean()
      }),
      (stateData) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Simulate initial state
          const initialState = {
            installedVersions: [...stateData.initialVersions],
            activeVersion: stateData.wasActiveVersion ? stateData.versionToUninstall : '',
            versionExists: stateData.initialVersions.includes(stateData.versionToUninstall)
          }
          
          // Simulate uninstall operation
          const uninstallOperation = {
            targetVersion: stateData.versionToUninstall,
            wasActive: stateData.wasActiveVersion && initialState.versionExists,
            success: stateData.uninstallSuccess && initialState.versionExists
          }
          
          // Simulate post-uninstall state
          const postUninstallState = {
            installedVersions: uninstallOperation.success 
              ? initialState.installedVersions.filter(v => v !== stateData.versionToUninstall)
              : [...initialState.installedVersions],
            activeVersion: (uninstallOperation.success && uninstallOperation.wasActive) 
              ? '' 
              : initialState.activeVersion,
            versionExists: !uninstallOperation.success && initialState.versionExists
          }
          
          // Verify state consistency
          expect(initialState).toHaveProperty('installedVersions')
          expect(initialState).toHaveProperty('activeVersion')
          expect(initialState).toHaveProperty('versionExists')
          
          expect(postUninstallState).toHaveProperty('installedVersions')
          expect(postUninstallState).toHaveProperty('activeVersion')
          expect(postUninstallState).toHaveProperty('versionExists')
          
          // Verify types
          expect(Array.isArray(initialState.installedVersions)).toBe(true)
          expect(Array.isArray(postUninstallState.installedVersions)).toBe(true)
          expect(typeof initialState.activeVersion).toBe('string')
          expect(typeof postUninstallState.activeVersion).toBe('string')
          expect(typeof initialState.versionExists).toBe('boolean')
          expect(typeof postUninstallState.versionExists).toBe('boolean')
          
          // Verify version format
          expect(stateData.versionToUninstall).toMatch(/^go\d+\.\d+\.\d+$/)
          initialState.installedVersions.forEach(version => {
            expect(version).toMatch(/^go\d+\.\d+\.\d+$/)
          })
          postUninstallState.installedVersions.forEach(version => {
            expect(version).toMatch(/^go\d+\.\d+\.\d+$/)
          })
          
          // Verify state transitions for successful uninstall
          if (uninstallOperation.success) {
            // Version should be removed from installed versions list
            expect(postUninstallState.installedVersions).not.toContain(stateData.versionToUninstall)
            expect(postUninstallState.installedVersions.length).toBe(
              Math.max(0, initialState.installedVersions.length - 1)
            )
            
            // If uninstalled version was active, active version should be cleared
            if (uninstallOperation.wasActive) {
              expect(postUninstallState.activeVersion).toBe('')
            }
            
            // Version should no longer exist
            expect(postUninstallState.versionExists).toBe(false)
          } else {
            // State should remain unchanged for failed uninstall
            expect(postUninstallState.installedVersions).toEqual(initialState.installedVersions)
            expect(postUninstallState.activeVersion).toBe(initialState.activeVersion)
            expect(postUninstallState.versionExists).toBe(initialState.versionExists)
          }
          
          // Verify active version consistency
          if (postUninstallState.activeVersion !== '') {
            expect(postUninstallState.installedVersions).toContain(postUninstallState.activeVersion)
          }
          
          // Verify no duplicate versions in installed list
          const uniqueVersions = [...new Set(postUninstallState.installedVersions)]
          expect(uniqueVersions.length).toBe(postUninstallState.installedVersions.length)
          
          // Verify uninstall operation properties
          expect(typeof uninstallOperation.success).toBe('boolean')
          expect(typeof uninstallOperation.wasActive).toBe('boolean')
          
          // If version didn't exist initially, uninstall should fail
          if (!initialState.versionExists) {
            expect(uninstallOperation.success).toBe(false)
          }
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 100 })
  })

  test('Property 9: Version Information Completeness', () => {
    // **Feature: go-version-management, Property 9: Version Information Completeness**
    fc.assert(fc.property(
      fc.array(fc.record({
        version: fc.string({ minLength: 1 }).filter(v => /^go\d+\.\d+\.\d+$/.test(v)),
        path: fc.string({ minLength: 1 }),
        isActive: fc.boolean(),
        goroot: fc.string({ minLength: 1 }),
        gopath: fc.string({ minLength: 1 })
      })),
      (mockVersions) => {
        const mockStore = new MockConfigStore()
        
        try {
          // Verify all version objects have required fields
          mockVersions.forEach(version => {
            expect(version).toHaveProperty('version')
            expect(version).toHaveProperty('path')
            expect(version).toHaveProperty('isActive')
            expect(version).toHaveProperty('goroot')
            expect(version).toHaveProperty('gopath')
            
            // Verify types
            expect(typeof version.version).toBe('string')
            expect(typeof version.path).toBe('string')
            expect(typeof version.isActive).toBe('boolean')
            expect(typeof version.goroot).toBe('string')
            expect(typeof version.gopath).toBe('string')
            
            // Verify version format
            expect(version.version).toMatch(/^go\d+\.\d+\.\d+$/)
            
            // Verify paths are non-empty
            expect(version.path.length).toBeGreaterThan(0)
            expect(version.goroot.length).toBeGreaterThan(0)
            expect(version.gopath.length).toBeGreaterThan(0)
          })
          
          // Verify at most one version can be active
          const activeVersions = mockVersions.filter(v => v.isActive)
          expect(activeVersions.length).toBeLessThanOrEqual(1)
          
          return true
        } finally {
          mockStore.cleanup()
        }
      }
    ), { numRuns: 10 })
  })
})