import { describe, expect, it } from 'vitest'
import { createEntitlements } from './index.js'
import { createTestDb, getGrant, listGrants, seedGrant, seedTierGrant, setTestNow } from './test-fixture.js'

describe('@platform-modules/entitlements', () => {
  it('can returns true for a live grant', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    setTestNow(db, new Date('2026-07-04T00:00:00.000Z'))
    await seedGrant(db, {
      account: 'acct_live',
      feature: 'feature:reports',
      tier: 'pro',
      expiresAt: new Date('2026-07-05T00:00:00.000Z'),
    })

    await expect(entitlements.can('acct_live', 'feature:reports')).resolves.toBe(true)
  })

  it('can returns false when a grant is missing', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    setTestNow(db, new Date('2026-07-04T00:00:00.000Z'))

    await expect(entitlements.can('acct_missing', 'feature:reports')).resolves.toBe(false)
  })

  it('can returns false when a grant is expired', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    setTestNow(db, new Date('2026-07-04T00:00:00.000Z'))
    await seedGrant(db, {
      account: 'acct_expired',
      feature: 'feature:reports',
      tier: 'pro',
      expiresAt: new Date('2026-07-03T23:59:59.999Z'),
    })

    await expect(entitlements.can('acct_expired', 'feature:reports')).resolves.toBe(false)
  })

  it('treats expiresAt equal to now as still live', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    const now = new Date('2026-07-04T00:00:00.000Z')
    setTestNow(db, now)
    await seedGrant(db, {
      account: 'acct_boundary',
      feature: 'feature:reports',
      tier: 'pro',
      expiresAt: now,
    })

    await expect(entitlements.can('acct_boundary', 'feature:reports')).resolves.toBe(true)
  })

  it('quota returns the stored tier quota for an active entitlement', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    setTestNow(db, new Date('2026-07-04T00:00:00.000Z'))
    await seedTierGrant(db, {
      capability: 'plugin:translate',
      tier: 'pro',
      quotaKey: 'translate:chars',
      quotaValue: 10,
    })
    await seedGrant(db, {
      account: 'acct_quota',
      feature: 'plugin:translate',
      tier: 'pro',
    })

    await expect(entitlements.quota('acct_quota', 'translate:chars')).resolves.toBe(10)
  })

  it('quota returns 0 when the subject has no active entitlement for the plugin capability', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    await seedTierGrant(db, {
      capability: 'plugin:translate',
      tier: 'pro',
      quotaKey: 'translate:chars',
      quotaValue: 10,
    })

    await expect(entitlements.quota('acct_missing', 'translate:chars')).resolves.toBe(0)
  })

  it('setTier is idempotent for the same capability+tier', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    const now = new Date('2026-07-04T12:00:00.000Z')
    setTestNow(db, now)
    await seedTierGrant(db, { capability: 'plugin:translate', tier: 'pro' })

    await entitlements.setTier('acct_tier', { capability: 'plugin:translate', tier: 'pro' })
    const firstRows = await listGrants(db, 'acct_tier')

    await entitlements.setTier('acct_tier', { capability: 'plugin:translate', tier: 'pro' })
    const secondRows = await listGrants(db, 'acct_tier')

    expect(secondRows).toEqual(firstRows)
  })

  it('setTier upserts the entitlement row for the referenced capability', async () => {
    const db = await createTestDb()
    const entitlements = createEntitlements({ db })
    setTestNow(db, new Date('2026-07-04T12:00:00.000Z'))
    await seedTierGrant(db, { capability: 'plugin:translate', tier: 'enterprise' })
    await seedTierGrant(db, {
      capability: 'plugin:translate',
      tier: 'enterprise',
      quotaKey: 'translate:chars',
      quotaValue: 100,
    })

    await entitlements.setTier(
      { account: 'acct_apply', tenancy: 'tenant_1' },
      { capability: 'plugin:translate', tier: 'enterprise' },
    )

    await expect(entitlements.can('acct_apply', 'plugin:translate')).resolves.toBe(true)
    await expect(entitlements.quota('acct_apply', 'translate:chars')).resolves.toBe(100)

    const grant = await getGrant(db, 'acct_apply', 'plugin:translate')
    expect(grant?.tier).toBe('enterprise')
  })
})
