import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'

import { createBillingStateStore } from '../billing-state'

const tempDirectories: string[] = []

afterEach(() => {
  while (tempDirectories.length > 0) {
    const directory = tempDirectories.pop()
    if (directory) {
      fs.rmSync(directory, { recursive: true, force: true })
    }
  }
})

function createTempStatePath() {
  const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'hypertwist-billing-state-'))
  tempDirectories.push(directory)
  return path.join(directory, 'billing-state.json')
}

describe('createBillingStateStore', () => {
  it('applies a subscription activation event and resolves download access', () => {
    const store = createBillingStateStore({
      statePath: createTempStatePath(),
      defaultPlan: 'free',
      defaultRole: 'operator',
    })

    const result = store.applyVerifiedPaddleEvent(JSON.stringify({
      event_id: 'evt_activated',
      event_type: 'subscription.activated',
      occurred_at: '2026-06-22T02:00:00.000Z',
      data: {
        id: 'sub_123',
        customer_id: 'ctm_123',
        status: 'active',
        custom_data: {
          email: 'operator@hypertwist.app',
          plan: 'studio',
        },
      },
    }))

    expect(result).toEqual({
      kind: 'applied',
      reason: 'processed',
      eventId: 'evt_activated',
      eventType: 'subscription.activated',
      email: 'operator@hypertwist.app',
    })

    expect(store.getEntitlementByEmail('operator@hypertwist.app')).toMatchObject({
      plan: 'studio',
      role: 'operator',
      canDownload: true,
      accessStatus: 'active',
      subscriptionId: 'sub_123',
      customerId: 'ctm_123',
      source: 'paddle',
    })
  })

  it('deduplicates a previously processed event id', () => {
    const store = createBillingStateStore({
      statePath: createTempStatePath(),
      defaultPlan: 'free',
      defaultRole: 'operator',
    })

    const rawEvent = JSON.stringify({
      event_id: 'evt_dupe',
      event_type: 'subscription.activated',
      occurred_at: '2026-06-22T02:00:00.000Z',
      data: {
        id: 'sub_dupe',
        status: 'active',
        custom_data: {
          email: 'operator@hypertwist.app',
          plan: 'operator',
        },
      },
    })

    expect(store.applyVerifiedPaddleEvent(rawEvent).kind).toBe('applied')
    expect(store.applyVerifiedPaddleEvent(rawEvent)).toEqual({
      kind: 'duplicate',
      reason: 'duplicate_event',
      eventId: 'evt_dupe',
      eventType: 'subscription.activated',
    })
  })

  it('ignores a stale event that arrives after a newer one', () => {
    const store = createBillingStateStore({
      statePath: createTempStatePath(),
      defaultPlan: 'free',
      defaultRole: 'operator',
    })

    expect(store.applyVerifiedPaddleEvent(JSON.stringify({
      event_id: 'evt_newer',
      event_type: 'subscription.activated',
      occurred_at: '2026-06-22T03:00:00.000Z',
      data: {
        id: 'sub_ordering',
        customer_id: 'ctm_ordering',
        status: 'active',
        custom_data: {
          email: 'operator@hypertwist.app',
          plan: 'operator',
        },
      },
    })).kind).toBe('applied')

    const staleResult = store.applyVerifiedPaddleEvent(JSON.stringify({
      event_id: 'evt_older',
      event_type: 'subscription.canceled',
      occurred_at: '2026-06-22T02:00:00.000Z',
      data: {
        id: 'sub_ordering',
        customer_id: 'ctm_ordering',
        status: 'canceled',
      },
    }))

    expect(staleResult).toEqual({
      kind: 'ignored',
      reason: 'stale_event',
      eventId: 'evt_older',
      eventType: 'subscription.canceled',
      email: 'operator@hypertwist.app',
    })
    expect(store.getEntitlementByEmail('operator@hypertwist.app')?.accessStatus).toBe('active')
  })

  it('resolves plans from configured price mappings and revokes on cancellation', () => {
    const store = createBillingStateStore({
      statePath: createTempStatePath(),
      defaultPlan: 'free',
      defaultRole: 'operator',
      pricePlanMap: {
        pri_operator: 'operator',
      },
    })

    expect(store.applyVerifiedPaddleEvent(JSON.stringify({
      event_id: 'evt_txn',
      event_type: 'transaction.completed',
      occurred_at: '2026-06-22T02:00:00.000Z',
      data: {
        id: 'txn_123',
        customer_id: 'ctm_456',
        custom_data: {
          email: 'operator@hypertwist.app',
        },
        items: [
          {
            price: {
              id: 'pri_operator',
            },
          },
        ],
      },
    })).kind).toBe('applied')

    expect(store.getEntitlementByEmail('operator@hypertwist.app')).toMatchObject({
      plan: 'operator',
      canDownload: true,
      transactionId: 'txn_123',
      subscriptionId: null,
      customerId: 'ctm_456',
    })

    expect(store.applyVerifiedPaddleEvent(JSON.stringify({
      event_id: 'evt_cancel',
      event_type: 'subscription.canceled',
      occurred_at: '2026-06-22T04:00:00.000Z',
      data: {
        id: 'sub_789',
        customer_id: 'ctm_456',
        status: 'canceled',
      },
    })).kind).toBe('applied')

    expect(store.getEntitlementByEmail('operator@hypertwist.app')).toMatchObject({
      plan: 'operator',
      canDownload: false,
      accessStatus: 'canceled',
      subscriptionId: 'sub_789',
    })
  })

  it('records unsupported payloads as noops without throwing', () => {
    const store = createBillingStateStore({
      statePath: createTempStatePath(),
      defaultPlan: 'free',
      defaultRole: 'operator',
    })

    expect(store.applyVerifiedPaddleEvent('{"not":"a-paddle-event"}')).toEqual({
      kind: 'noop',
      reason: 'unsupported_payload',
      eventId: 'unknown',
      eventType: 'unknown',
    })
  })
})
