import { getTableName, sql } from 'drizzle-orm'
import { describe, expect, it } from 'vitest'
import { createPgliteClient } from '@platform-modules/db/pglite'
import {
  accounts,
  apiKeys,
  auditLog,
  authUsers,
  chargeIntents,
  credentials,
  entitlementTierGrants,
  entitlements,
  invoiceDocument,
  invoiceReferences,
  ledgerEntries,
  members,
  oauthClients,
  oauthCodes,
  oauthTokens,
  periodKey,
  plugins,
  pressZoneInitSql,
  pressZoneSchema,
  serviceTokens,
  sites,
  subscriptionPackages,
  subscriptions,
  tenancyPermissions,
  tenancyRolePermissions,
  tenancyRoles,
  userSessions,
  walletBalances,
  webhookEvents,
} from './schema.js'

const TABLE_NAMES = [
  'accounts',
  'plugins',
  'subscription_packages',
  'subscriptions',
  'sites',
  'credentials',
  'members',
  'invoice_references',
  'invoice_document',
  'webhook_events',
  'charge_intents',
  'auth_users',
  'user_sessions',
  'service_tokens',
  'api_keys',
  'oauth_clients',
  'oauth_codes',
  'oauth_tokens',
  'entitlements',
  'entitlement_tier_grants',
  'tenancy_roles',
  'tenancy_permissions',
  'tenancy_role_permissions',
  'audit_log',
  'ledger_entries',
  'wallet_balances',
] as const

describe('pressZoneSchema', () => {
  it('exposes all app and composed module tables', () => {
    expect(getTableName(accounts)).toBe('accounts')
    expect(getTableName(plugins)).toBe('plugins')
    expect(getTableName(subscriptionPackages)).toBe('subscription_packages')
    expect(getTableName(subscriptions)).toBe('subscriptions')
    expect(getTableName(sites)).toBe('sites')
    expect(getTableName(credentials)).toBe('credentials')
    expect(getTableName(members)).toBe('members')
    expect(getTableName(invoiceReferences)).toBe('invoice_references')
    expect(getTableName(invoiceDocument)).toBe('invoice_document')
    expect(getTableName(webhookEvents)).toBe('webhook_events')
    expect(getTableName(chargeIntents)).toBe('charge_intents')
    expect(getTableName(authUsers)).toBe('auth_users')
    expect(getTableName(userSessions)).toBe('user_sessions')
    expect(getTableName(serviceTokens)).toBe('service_tokens')
    expect(getTableName(apiKeys)).toBe('api_keys')
    expect(getTableName(oauthClients)).toBe('oauth_clients')
    expect(getTableName(oauthCodes)).toBe('oauth_codes')
    expect(getTableName(oauthTokens)).toBe('oauth_tokens')
    expect(getTableName(entitlements)).toBe('entitlements')
    expect(getTableName(entitlementTierGrants)).toBe('entitlement_tier_grants')
    expect(getTableName(tenancyRoles)).toBe('tenancy_roles')
    expect(getTableName(tenancyPermissions)).toBe('tenancy_permissions')
    expect(getTableName(tenancyRolePermissions)).toBe('tenancy_role_permissions')
    expect(getTableName(auditLog)).toBe('audit_log')
    expect(getTableName(ledgerEntries)).toBe('ledger_entries')
    expect(getTableName(walletBalances)).toBe('wallet_balances')
    expect(Object.keys(pressZoneSchema)).toEqual([
      'accounts',
      'plugins',
      'subscriptionPackages',
      'subscriptions',
      'sites',
      'credentials',
      'members',
      'invoiceReferences',
      'invoiceDocument',
      'webhookEvents',
      'chargeIntents',
      'refundReservations',
      'authUsers',
      'userSessions',
      'serviceTokens',
      'apiKeys',
      'oauthClients',
      'oauthCodes',
      'oauthTokens',
      'entitlements',
      'entitlementTierGrants',
      'tenancyRoles',
      'tenancyPermissions',
      'tenancyRolePermissions',
      'auditLog',
      'ledgerEntries',
      'walletBalances',
    ])
  })
})

describe('pressZoneInitSql', () => {
  it('applies cleanly on a fresh pglite database and makes every table queryable', async () => {
    const db = createPgliteClient({ schema: pressZoneSchema })

    expect(pressZoneInitSql).toContain('CREATE TABLE IF NOT EXISTS accounts')
    expect(pressZoneInitSql).toContain('CREATE TABLE IF NOT EXISTS api_keys')
    expect(pressZoneInitSql).toContain('CREATE TABLE IF NOT EXISTS oauth_clients')
    expect(pressZoneInitSql).toContain('CREATE TABLE IF NOT EXISTS ledger_entries')
    expect(pressZoneInitSql).toContain('CREATE TABLE IF NOT EXISTS wallet_balances')

    for (const statement of pressZoneInitSql.split(';').map((part) => part.trim()).filter(Boolean)) {
      await db.execute(sql.raw(statement))
    }

    for (const tableName of TABLE_NAMES) {
      await expect(db.execute(sql.raw(`SELECT 1 FROM ${tableName} LIMIT 1`))).resolves.toBeTruthy()
    }
  })
})

describe('periodKey', () => {
  it('formats the wallet owner id as <account>:<plugin>:<period>', () => {
    expect(periodKey('acct_123', 'translate', '2026-07')).toBe('acct_123:translate:2026-07')
  })
})
