import { DSLCompiler } from '../DSLCompiler.js';
import { Arbiter } from '../../core/Arbiter.js';

/**
 * Progressive Test Suite - Tests each language feature incrementally
 */
export function runProgressiveTestSuite() {
  console.log('=== Progressive DSL Test Suite ===\n');

  const arbiter = new Arbiter();
  const compiler = new DSLCompiler(arbiter);

  const tests = [
    {
      name: '1. Basic Definitions',
      dsl: `
definition User {
  name: string
  age: number
}`,
      expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
    },
    {
      name: '2. Definitions with Arrays',
      dsl: `
definition User {
  name: string
  roles: string[]
  permissions: Permission[]
}`,
      expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
    },
    {
      name: '3. Definitions with Behaviors',
      dsl: `
definition User {
  name: string
  lastActive: timestamp BEHAVES {
    decaying down hourly
  }
  score: number BEHAVES {
    blurring adaptive confidence_95
  }
  session: string BEHAVES {
    ttl 24h
  }
}`,
      expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
    },
    {
      name: '4. Definitions with Cache Directives',
      dsl: `
definition User {
  name: string
  lastActive: timestamp BEHAVES {
    decaying down hourly
  } CACHE lazy
  score: number BEHAVES {
    blurring adaptive confidence_95
  } CACHE eager
}`,
      expected: { definitions: 1, facts: 0, evidence: 0, measures: 0 }
    },
    {
      name: '5. Basic Facts',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)
fact isActive(user: User)`,
      expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
    },
    {
      name: '6. Facts with Properties',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string) CACHE eager
fact isMember(user: User, group: Group) transitive CACHE lazy
fact isFriend(user: User, friend: User) symmetrical`,
      expected: { definitions: 1, facts: 3, evidence: 0, measures: 0 }
    },
    {
      name: '7. Facts with Limits',
      dsl: `
definition User {
  name: string
}

fact isMember(user: User, group: Group) transitive limit 10
fact isFriend(user: User, friend: User) symmetrical limit 100`,
      expected: { definitions: 1, facts: 2, evidence: 0, measures: 0 }
    },
    {
      name: '8. Simple Evidence',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)

evidence canRead(user: User, doc: Document) {
  hasRole(user, 'admin')
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '9. Evidence with Multiple Statements',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)
fact owns(user: User, doc: Document)

evidence canRead(user: User, doc: Document) {
  owns(user, doc)
  hasRole(user, 'admin')
}`,
      expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
    },
    {
      name: '10. Evidence with ALWAYS',
      dsl: `
definition User {
  name: string
}

fact isActive(user: User)

evidence canRead(user: User, doc: Document) {
  ALWAYS isActive(user)
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '11. Evidence with REQUIRES',
      dsl: `
definition User {
  name: string
}

fact hasClearance(user: User, level: string)

evidence canRead(user: User, doc: Document) {
  REQUIRES hasClearance(user, doc.level)
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '12. Evidence with WHEN',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)

evidence canRead(user: User, doc: Document) {
  WHEN hasRole(user, 'admin')
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '13. Evidence with WHEN UNLESS',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)
fact isSuspended(user: User)

evidence canRead(user: User, doc: Document) {
  WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
}`,
      expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
    },
    {
      name: '14. Evidence with Pattern Matching',
      dsl: `
definition User {
  name: string
}

fact isMember(user: User, group: Group)

evidence canRead(user: User, doc: Document) {
  isMember(user, *group) {
    canRead(group, doc)
  }
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '15. Evidence with Pattern Matching and Limits',
      dsl: `
definition User {
  name: string
}

fact isMember(user: User, group: Group)

evidence canRead(user: User, doc: Document) {
  isMember(user, *group) {
    canRead(group, doc)
  } limit 5
}`,
      expected: { definitions: 1, facts: 1, evidence: 1, measures: 0 }
    },
    {
      name: '16. Evidence with Fusion',
      dsl: `
definition User {
  name: string
}

fact hasRole(user: User, role: string)
fact isMember(user: User, group: Group)

evidence canRead(user: User, doc: Document) {
  fusion max {
    hasRole(user, 'admin')
    isMember(user, *group) {
      canRead(group, doc)
    }
  }
}`,
      expected: { definitions: 1, facts: 2, evidence: 1, measures: 0 }
    },
    {
      name: '17. Basic Measures',
      dsl: `
definition User {
  name: string
  role: string
}

measure userRole(user: User) {
  user.role
} PROVIDES string`,
      expected: { definitions: 1, facts: 0, evidence: 0, measures: 1 }
    },
    {
      name: '18. Measures with Fusion',
      dsl: `
definition User {
  name: string
  role: string
}

fact hasRole(user: User, role: string)

measure userPermissions(user: User) {
  fusion max {
    user.role.permissions
    hasRole(user, 'admin')
  }
} PROVIDES Permission[]`,
      expected: { definitions: 1, facts: 1, evidence: 0, measures: 1 }
    },
    {
      name: '19. Complete Example',
      dsl: `
definition User {
  role: string
  isActive: boolean
  lastActive: timestamp BEHAVES {
    decaying down hourly
  } CACHE lazy
}

definition Document {
  level: string
  owner: User
}

fact hasRole(user: User, role: string) CACHE eager
fact owns(user: User, doc: Document) CACHE eager

evidence canRead(user: User, doc: Document) {
  owns(user, doc)
  
  WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
}

measure userRole(user: User) {
  user.role
} PROVIDES string`,
      expected: { definitions: 2, facts: 2, evidence: 1, measures: 1 }
    }
  ];

  let passed = 0;
  let failed = 0;

  for (const test of tests) {
    console.log(`\n--- ${test.name} ---`);
    
    try {
      const result = compiler.compile(test.dsl, `test-${passed + failed + 1}`);
      
      const actual = {
        definitions: result.program.definitions.length,
        facts: result.program.facts.length,
        evidence: result.program.evidence.length,
        measures: result.program.measures.length
      };
      
      const success = result.success && 
        actual.definitions === test.expected.definitions &&
        actual.facts === test.expected.facts &&
        actual.evidence === test.expected.evidence &&
        actual.measures === test.expected.measures;
      
      if (success) {
        console.log('✅ PASSED');
        console.log(`   Definitions: ${actual.definitions}, Facts: ${actual.facts}, Evidence: ${actual.evidence}, Measures: ${actual.measures}`);
        passed++;
      } else {
        console.log('❌ FAILED');
        console.log(`   Expected: ${JSON.stringify(test.expected)}`);
        console.log(`   Actual: ${JSON.stringify(actual)}`);
        if (result.errors.length > 0) {
          console.log(`   Errors: ${result.errors.join(', ')}`);
        }
        failed++;
      }
    } catch (error) {
      console.log('❌ FAILED');
      console.log(`   Error: ${error.message}`);
      failed++;
    }
  }

  console.log(`\n=== Test Suite Results ===`);
  console.log(`Total Tests: ${passed + failed}`);
  console.log(`Passed: ${passed}`);
  console.log(`Failed: ${failed}`);
  console.log(`Success Rate: ${((passed / (passed + failed)) * 100).toFixed(1)}%`);

  return { passed, failed, total: passed + failed };
}

// Run the test suite
runProgressiveTestSuite();
