/**
 * Tier-gate and scope-limit verification — zapier-make-integration (wave-13).
 *
 * Tests:
 * 1. OAuth→ApiScope mapping is correct for all Zapier/Make scopes
 * 2. hasScope works with mapped scopes
 * 3. SCOPE_MAP covers all new endpoints
 */
import { describe, it, expect } from 'vitest'
import {
  mapOAuthScopesToApiScopes,
  hasScope,
  SCOPE_MAP,
} from '../src/index'

// ── OAuth → ApiScope mapping tests ───────────────────────────────────────────

describe('mapOAuthScopesToApiScopes', () => {
  it('maps write:leads → leads:write', () => {
    const result = mapOAuthScopesToApiScopes('write:leads')
    expect(result).toContain('leads:write')
  })

  it('maps read:time → time:read', () => {
    const result = mapOAuthScopesToApiScopes('read:time')
    expect(result).toContain('time:read')
  })

  it('maps all Zapier/Make scopes correctly', () => {
    const oauthScope = 'read:invoices write:invoices read:customers write:customers read:leads write:leads read:time write:time read:events read:projects write:tasks'
    const result = mapOAuthScopesToApiScopes(oauthScope)
    expect(result).toContain('invoices:read')
    expect(result).toContain('invoices:write')
    expect(result).toContain('customers:read')
    expect(result).toContain('customers:write')
    expect(result).toContain('leads:read')
    expect(result).toContain('leads:write')
    expect(result).toContain('time:read')
    expect(result).toContain('time:write')
    expect(result).toContain('events:read')
    expect(result).toContain('projects:read')
    expect(result).toContain('tasks:write')
  })

  it('drops unknown OAuth scope tokens', () => {
    const result = mapOAuthScopesToApiScopes('read:unknown_resource')
    expect(result).toHaveLength(0)
  })

  it('handles empty scope string', () => {
    const result = mapOAuthScopesToApiScopes('')
    expect(result).toHaveLength(0)
  })
})

// ── hasScope + OAuth mapping tests ───────────────────────────────────────────

describe('hasScope with OAuth-mapped scopes', () => {
  it('write:leads authorizes POST /v1/leads (leads:write)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:leads')
    expect(hasScope(apiScopes, 'leads:write')).toBe(true)
  })

  it('write:leads also authorizes GET /v1/leads (leads:read implied)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:leads')
    expect(hasScope(apiScopes, 'leads:read')).toBe(true)
  })

  it('write:leads does NOT authorize POST /v1/invoices (invoices:write)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:leads')
    expect(hasScope(apiScopes, 'invoices:write')).toBe(false)
  })

  it('read:customers only does NOT authorize POST /v1/leads', () => {
    const apiScopes = mapOAuthScopesToApiScopes('read:customers')
    expect(hasScope(apiScopes, 'leads:write')).toBe(false)
  })

  it('read:customers only does NOT authorize POST /v1/time', () => {
    const apiScopes = mapOAuthScopesToApiScopes('read:customers')
    expect(hasScope(apiScopes, 'time:write')).toBe(false)
  })

  it('write:time authorizes POST /v1/time (time:write)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:time')
    expect(hasScope(apiScopes, 'time:write')).toBe(true)
  })

  it('read:projects authorizes GET /v1/projects (projects:read)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('read:projects')
    expect(hasScope(apiScopes, 'projects:read')).toBe(true)
  })

  it('write:tasks authorizes POST /v1/tasks (tasks:write)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:tasks')
    expect(hasScope(apiScopes, 'tasks:write')).toBe(true)
  })

  it('write:invoices authorizes POST /v1/invoices/:id/send (invoices:write)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('write:invoices')
    expect(hasScope(apiScopes, 'invoices:write')).toBe(true)
  })

  it('read:events authorizes POST /v1/webhooks (events:read)', () => {
    const apiScopes = mapOAuthScopesToApiScopes('read:events')
    expect(hasScope(apiScopes, 'events:read')).toBe(true)
  })

  it('Zapier/Make scopes do NOT include any admin or settings scope', () => {
    const oauthScope = 'read:invoices write:invoices read:customers write:customers read:leads write:leads read:time write:time read:events read:projects write:tasks'
    const apiScopes = mapOAuthScopesToApiScopes(oauthScope)
    // No admin scopes exist in OAUTH_SCOPE_TO_API_SCOPE — none of these should pass
    // These are not valid ApiScope values, so hasScope returns false naturally.
    // We verify the mapped set contains only the expected scopes.
    expect(apiScopes).not.toContain('admin:write')
    expect(apiScopes).not.toContain('settings:write')
    expect(apiScopes).toHaveLength(11)
  })
})

// ── SCOPE_MAP coverage tests ──────────────────────────────────────────────────

describe('SCOPE_MAP new endpoint coverage', () => {
  it('covers GET /v1/leads', () => {
    expect(SCOPE_MAP['GET /v1/leads']).toBe('leads:read')
  })

  it('covers POST /v1/leads', () => {
    expect(SCOPE_MAP['POST /v1/leads']).toBe('leads:write')
  })

  it('covers PATCH /v1/leads/:id', () => {
    expect(SCOPE_MAP['PATCH /v1/leads/:id']).toBe('leads:write')
  })

  it('covers POST /v1/time', () => {
    expect(SCOPE_MAP['POST /v1/time']).toBe('time:write')
  })

  it('covers POST /v1/invoices/:id/send', () => {
    expect(SCOPE_MAP['POST /v1/invoices/:id/send']).toBe('invoices:write')
  })

  it('covers GET /v1/webhooks', () => {
    expect(SCOPE_MAP['GET /v1/webhooks']).toBe('events:read')
  })

  it('covers POST /v1/webhooks', () => {
    expect(SCOPE_MAP['POST /v1/webhooks']).toBe('events:read')
  })

  it('covers DELETE /v1/webhooks/:id', () => {
    expect(SCOPE_MAP['DELETE /v1/webhooks/:id']).toBe('events:read')
  })

  it('covers GET /v1/projects', () => {
    expect(SCOPE_MAP['GET /v1/projects']).toBe('projects:read')
  })

  it('covers POST /v1/tasks', () => {
    expect(SCOPE_MAP['POST /v1/tasks']).toBe('tasks:write')
  })
})
