import { describe, test } from 'node:test';
import assert from 'node:assert/strict';
import { DSLCompiler } from '../../src/ast/DSLCompiler.js';

function createMockArbiter() {
  const relationConfigs = new Map();
  return {
    relationConfigs,
    setRelationConfig(relation, config) {
      relationConfigs.set(relation, config);
    }
  };
}

describe('Integration Tests', () => {
  const arbiter = createMockArbiter();
  const compiler = new DSLCompiler(arbiter);

  test('Complete authorization system', () => {
    const completeSystem = `
      // Type definitions with complex behaviors
      definition User {
        role: string
        isActive: boolean
        lastActive: timestamp BEHAVES {
          decaying down hourly
        } CACHE lazy
        isSuspended: boolean
        balance: number BEHAVES {
          decaying down hourly
        } CACHE eager
        score: number BEHAVES {
          blurring adaptive confidence_95
        } CACHE lazy
        session: string BEHAVES {
          ttl 24h
        } CACHE eager
        clearance: string BEHAVES {
          blurring fixed
        } CACHE eager
        reputation: number BEHAVES {
          decaying up daily
        } CACHE lazy
      }

      definition Group {
        name: string
        permissions: Permission[]
        level: string
        isPublic: boolean CACHE eager
        created: timestamp BEHAVES {
          decaying stable monthly
        } CACHE lazy
      }

      definition Document {
        level: string
        owner: User
        tags: string[]
        content: string BEHAVES {
          blurring fixed
        } CACHE lazy
        accessCount: number BEHAVES {
          decaying up daily
        } CACHE eager
        expiresAt: timestamp BEHAVES {
          ttl 30d
        } CACHE eager
        isPublic: boolean CACHE eager
      }

      definition Resource {
        level: string
        owner: User
        permissions: Permission[]
        isPublic: boolean CACHE eager
        accessCount: number BEHAVES {
          decaying up daily
        } CACHE eager
      }

      // Facts with various properties and caching
      fact hasRole(user: User, role: string) CACHE eager
      fact isMember(user: User, group: Group) transitive CACHE lazy limit 10
      fact isFriend(user: User, friend: User) symmetrical CACHE eager limit 100
      fact owns(user: User, doc: Document) CACHE eager
      fact isSuspended(user: User) CACHE lazy
      fact hasPermission(user: User, resource: Resource, action: string) CACHE eager
      fact isAdmin(user: User) CACHE eager
      fact isOwner(user: User, resource: Resource) CACHE eager
      fact hasAccess(user: User, resource: Resource, level: string) CACHE lazy
      fact isColleague(user: User, colleague: User) symmetrical CACHE lazy limit 50
      fact isParentOf(parent: User, child: User) transitive CACHE eager limit 3

      // Evidence rules with complex logic
      evidence canRead(user: User, doc: Document) {
        owns(user, doc)

        isMember(user, *group) {
          canRead(group, doc)
        } limit 5

        parentOf(user, *parent) {
          canRead(parent, doc)
        } limit 3

        similar(doc, *similar) |similarity| {
          canRead(user, similar)
        } with similarity > 0.7 limit 5

        WHEN hasRole(user, 'admin') UNLESS isSuspended(user)
      }

      evidence canWrite(user: User, doc: Document) {
        owns(user, doc)

        isMember(user, *group) {
          canWrite(group, doc)
        } limit 3

        WHEN hasRole(user, 'admin') UNLESS isSuspended(user)

        REQUIRES user.isActive
      }

      evidence canDelete(user: User, doc: Document) {
        owns(user, doc)

        ALWAYS user.isActive

        WHEN hasRole(user, 'admin') UNLESS isSuspended(user)

        REQUIRES user.isActive
      }

      evidence canAccessCritical(user: User, resource: Resource) {
        fusion min {
          hasClearance(user, resource.level)
          user.isActive
          NOT user.isBlacklisted
        }

        fusion max {
          hasRole(user, 'admin')
          fusion majority {
            hasClearance(user, 'secret')
            user.isTrusted
            user.lastActive within 1hr
          }
        }
      }

      evidence canAccessSensitive(user: User, doc: Document) {
        ALWAYS user.isActive

        WHEN hasRole(user, 'admin') UNLESS isSuspended(user)

        REQUIRES hasClearance(user, doc.level)

        fusion majority {
          user.isTrusted
          user.hasRecentActivity
        }
      }

      // Measures for computed values
      measure userRole(user: User) {
        user.role
      } PROVIDES string

      measure userPermissions(user: User) {
        fusion max {
          user.role.permissions
          user.group.permissions
        }
      } PROVIDES Permission[]

      measure effectiveClearance(user: User) {
        fusion majority {
          user.clearance
          user.role.clearance
          user.group.clearance
        }
      } PROVIDES string

      measure userTrustScore(user: User) {
        fusion average {
          user.reputation
          user.activityScore
          user.verificationLevel
        }
      } PROVIDES number

      measure userBalance(user: User) {
        user.balance
      } PROVIDES number

      measure userScore(user: User) {
        user.score
      } PROVIDES number
    `;

    const result = compiler.compile(completeSystem, 'test-complete-system');
    assert.ok(result.success, 'Complete authorization system should compile successfully');
    assert.ok(result.program.definitions.length >= 4, 'Should have multiple definitions');
    assert.ok(result.program.facts.length >= 10, 'Should have multiple facts');
    assert.ok(result.program.evidence.length >= 5, 'Should have multiple evidence rules');
    assert.ok(result.program.measures.length >= 6, 'Should have multiple measures');
  });

  test('Multi-domain system', () => {
    const multiDomain = `
      // Authentication domain
      definition User {
        role: string
        isActive: boolean
        lastActive: timestamp BEHAVES { decaying down hourly } CACHE lazy
        session: string BEHAVES { ttl 24h } CACHE eager
      }

      fact hasRole(user: User, role: string) CACHE eager
      fact isActive(user: User) CACHE eager

      evidence canAuthenticate(user: User) {
        user.isActive
        user.session within 24h
      }

      // Authorization domain
      definition Resource {
        level: string
        owner: User
        permissions: Permission[]
      }

      fact owns(user: User, resource: Resource) CACHE eager
      fact hasPermission(user: User, resource: Resource, action: string) CACHE eager

      evidence canAccess(user: User, resource: Resource) {
        owns(user, resource)
        hasPermission(user, resource, 'read')
      }

      // Finance domain
      definition Account {
        balance: number BEHAVES { decaying down hourly } CACHE eager
        owner: User
        isActive: boolean CACHE eager
      }

      fact hasAccount(user: User, account: Account) CACHE eager
      fact hasBalance(user: User, amount: number) CACHE eager

      evidence canWithdraw(user: User, amount: number) {
        hasBalance(user, amount)
        user.isActive
      }

      // Social domain
      definition Group {
        name: string
        members: User[]
        isPublic: boolean CACHE eager
      }

      fact isMember(user: User, group: Group) transitive CACHE lazy limit 10
      fact isFriend(user: User, friend: User) symmetrical CACHE eager limit 100

      evidence canAccessGroup(user: User, group: Group) {
        isMember(user, group)
        group.isPublic
      }
    `;

    const result = compiler.compile(multiDomain, 'test-multi-domain');
    assert.ok(result.success, 'Multi-domain system should compile successfully');
    assert.ok(result.program.definitions.length >= 4, 'Should have multiple domain definitions');
    assert.ok(result.program.facts.length >= 8, 'Should have multiple domain facts');
    assert.ok(result.program.evidence.length >= 4, 'Should have multiple domain evidence rules');
  });

  test('Hierarchical access', () => {
    const hierarchicalSystem = `
      definition User {
        role: string
        level: string
        isActive: boolean
        clearance: string
      }

      definition Organization {
        name: string
        level: string
        parent: Organization
      }

      fact isMember(user: User, org: Organization) transitive CACHE lazy limit 5
      fact isParentOf(parent: Organization, child: Organization) transitive CACHE eager limit 3
      fact hasRole(user: User, role: string) CACHE eager
      fact hasClearance(user: User, level: string) CACHE eager

      evidence canAccessOrg(user: User, org: Organization) {
        isMember(user, org)

        isParentOf(org, *parentOrg) {
          canAccessOrg(user, parentOrg)
        } limit 3

        WHEN hasRole(user, 'admin') UNLESS user.isSuspended
      }

      evidence canAccessResource(user: User, resource: Resource) {
        isMember(user, *org) {
          canAccessResource(org, resource)
        } limit 5

        parentOf(user, *parent) {
          canAccessResource(parent, resource)
        } limit 2
      }
    `;

    const result = compiler.compile(hierarchicalSystem, 'test-hierarchical');
    assert.ok(result.success, 'Hierarchical access system should compile successfully');
  });

  test('Similarity-based access', () => {
    const similaritySystem = `
      definition User {
        profile: string
        interests: string[]
        isActive: boolean
      }

      definition Document {
        content: string
        tags: string[]
        isPublic: boolean
        owner: User
      }

      fact isFriend(user: User, friend: User) symmetrical CACHE eager limit 100
      fact hasInterest(user: User, interest: string) CACHE lazy
      fact hasTag(doc: Document, tag: string) CACHE lazy

      evidence canRead(user: User, doc: Document) {
        owns(user, doc)

        similar(doc, *similar) |similarity| {
          canRead(user, similar)
          similar.isPublic
        } with similarity > 0.7 limit 10

        isFriend(user, *friend) {
          canRead(friend, doc)
        } limit 5

        fusion majority {
          user.interests
          doc.tags
        }
      }

      evidence canRecommend(user: User, doc: Document) {
        similar(user, *similarUser) |similarity| {
          canRead(similarUser, doc)
        } with similarity > 0.8 limit 20

        fusion average {
          user.profile
          doc.content
        }
      }
    `;

    const result = compiler.compile(similaritySystem, 'test-similarity');
    assert.ok(result.success, 'Similarity-based access system should compile successfully');
  });

  test('Temporal access', () => {
    const temporalSystem = `
      definition User {
        lastActive: timestamp BEHAVES { decaying down hourly } CACHE lazy
        session: string BEHAVES { ttl 24h } CACHE eager
        isActive: boolean
      }

      definition Event {
        startTime: timestamp
        endTime: timestamp
        isPublic: boolean
      }

      fact hasAccess(user: User, event: Event) CACHE lazy
      fact isParticipant(user: User, event: Event) CACHE eager

      evidence canAccessEvent(user: User, event: Event) {
        user.lastActive within 1h

        isParticipant(user, event)

        WHEN event.isPublic UNLESS user.isSuspended

        fusion min {
          user.session within 24h
          user.isActive
        }
      }

      evidence canAccessHistorical(user: User, event: Event) {
        user.lastActive within 24h

        fusion majority {
          user.isActive
          user.session within 24h
          event.isPublic
        }
      }
    `;

    const result = compiler.compile(temporalSystem, 'test-temporal');
    assert.ok(result.success, 'Temporal access system should compile successfully');
  });

  test('Complex behaviors', () => {
    const behaviorSystem = `
      definition User {
        balance: number BEHAVES { decaying down hourly } CACHE eager
        score: number BEHAVES { blurring adaptive confidence_95 } CACHE lazy
        session: string BEHAVES { ttl 24h } CACHE eager
        reputation: number BEHAVES { decaying up daily } CACHE lazy
        clearance: string BEHAVES { blurring fixed } CACHE eager
        lastActive: timestamp BEHAVES { decaying down hourly } CACHE lazy
      }

      definition Document {
        content: string BEHAVES { blurring fixed } CACHE lazy
        accessCount: number BEHAVES { decaying up daily } CACHE eager
        expiresAt: timestamp BEHAVES { ttl 30d } CACHE eager
        isPublic: boolean CACHE eager
      }

      fact hasBalance(user: User, amount: number) CACHE eager
      fact hasScore(user: User, score: number) CACHE lazy
      fact hasReputation(user: User, reputation: number) CACHE lazy

      evidence canAccessDocument(user: User, doc: Document) {
        user.balance > 0

        user.score > 0.5

        user.reputation > 0.3

        doc.accessCount < 1000

        fusion majority {
          user.isActive
          user.lastActive within 1h
          doc.isPublic
        }
      }

      measure userEffectiveScore(user: User) {
        fusion average {
          user.score
          user.reputation
          user.balance
        }
      } PROVIDES number

      measure documentPopularity(doc: Document) {
        doc.accessCount
      } PROVIDES number
    `;

    const result = compiler.compile(behaviorSystem, 'test-behaviors');
    assert.ok(result.success, 'Complex behaviors system should compile successfully');
  });

  test('Performance scenarios', () => {
    const performanceSystem = `
      definition User {
        role: string
        isActive: boolean
        permissions: Permission[] CACHE eager
      }

      definition Resource {
        level: string
        owner: User
        permissions: Permission[] CACHE eager
      }

      // High-frequency facts with limits
      fact isMember(user: User, group: Group) transitive CACHE lazy limit 5
      fact isFriend(user: User, friend: User) symmetrical CACHE eager limit 50
      fact hasPermission(user: User, resource: Resource, action: string) CACHE eager
      fact owns(user: User, resource: Resource) CACHE eager

      // Optimized evidence rules
      evidence canAccess(user: User, resource: Resource) {
        owns(user, resource)

        isMember(user, *group) {
          canAccess(group, resource)
        } limit 3

        WHEN hasPermission(user, resource, 'read')
      }

      evidence canModify(user: User, resource: Resource) {
        owns(user, resource)

        isMember(user, *group) {
          canModify(group, resource)
        } limit 2

        WHEN hasPermission(user, resource, 'write')
      }

      // Efficient measures
      measure userEffectivePermissions(user: User) {
        user.permissions
      } PROVIDES Permission[]

      measure resourceAccessLevel(resource: Resource) {
        resource.level
      } PROVIDES string
    `;

    const result = compiler.compile(performanceSystem, 'test-performance');
    assert.ok(result.success, 'Performance scenarios should compile successfully');
  });
});
