/**
 * Tests for workflow access middleware — focused on the workspace-scoped
 * API key boundary check in the `requireDeployment=false` branch.
 *
 * @vitest-environment node
 */

import {
  hybridAuthMockFns,
  workflowAuthzMock,
  workflowAuthzMockFns,
  workflowsUtilsMock,
  workflowsUtilsMockFns,
} from '@sim/testing'
import { NextRequest } from 'next/server'
import { beforeEach, describe, expect, it, vi } from 'vitest'

vi.mock('@/lib/workflows/utils', () => workflowsUtilsMock)
vi.mock('@sim/platform-authz/workflow', () => workflowAuthzMock)
vi.mock('@/lib/api-key/service', () => ({
  authenticateApiKeyFromHeader: vi.fn(),
  updateApiKeyLastUsed: vi.fn(),
}))

import { validateWorkflowAccess } from '@/app/api/workflows/middleware'

function makeRequest() {
  return new NextRequest(new URL('https://example.com/api/workflows/wf-1/log'))
}

describe('validateWorkflowAccess (requireDeployment=false)', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    workflowsUtilsMockFns.mockGetWorkflowById.mockResolvedValue({
      id: 'wf-1',
      workspaceId: 'ws-A',
      isDeployed: true,
    })
    workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission.mockResolvedValue({
      allowed: true,
      status: 200,
      workflow: { id: 'wf-1', workspaceId: 'ws-A' },
    })
  })

  it('rejects a workspace-scoped API key issued for a different workspace', async () => {
    hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValueOnce({
      success: true,
      userId: 'user-1',
      authType: 'api_key',
      apiKeyType: 'workspace',
      workspaceId: 'ws-B',
    })

    const result = await validateWorkflowAccess(makeRequest(), 'wf-1', false)

    expect(result.error).toEqual({
      message: 'API key is not authorized for this workspace',
      status: 403,
    })
    expect(workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission).not.toHaveBeenCalled()
  })

  it('allows a workspace-scoped API key issued for the matching workspace', async () => {
    hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValueOnce({
      success: true,
      userId: 'user-1',
      authType: 'api_key',
      apiKeyType: 'workspace',
      workspaceId: 'ws-A',
    })

    const result = await validateWorkflowAccess(makeRequest(), 'wf-1', false)

    expect(result.error).toBeUndefined()
    expect(result.workflow).toBeDefined()
    expect(result.auth?.workspaceId).toBe('ws-A')
    expect(workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission).toHaveBeenCalledWith({
      workflowId: 'wf-1',
      userId: 'user-1',
      action: 'read',
    })
  })

  it('allows a personal API key regardless of workspaceId on the auth result', async () => {
    hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValueOnce({
      success: true,
      userId: 'user-1',
      authType: 'api_key',
      apiKeyType: 'personal',
      workspaceId: 'ws-B',
    })

    const result = await validateWorkflowAccess(makeRequest(), 'wf-1', false)

    expect(result.error).toBeUndefined()
    expect(result.workflow).toBeDefined()
  })

  it('allows session auth (no apiKeyType) when workspace permission grants access', async () => {
    hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValueOnce({
      success: true,
      userId: 'user-1',
      authType: 'session',
    })

    const result = await validateWorkflowAccess(makeRequest(), 'wf-1', false)

    expect(result.error).toBeUndefined()
    expect(result.workflow).toBeDefined()
  })

  it('still enforces workspace-permission rejection for personal keys', async () => {
    hybridAuthMockFns.mockCheckHybridAuth.mockResolvedValueOnce({
      success: true,
      userId: 'user-1',
      authType: 'api_key',
      apiKeyType: 'personal',
    })
    workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission.mockResolvedValueOnce({
      allowed: false,
      status: 403,
      message: 'Access denied',
    })

    const result = await validateWorkflowAccess(makeRequest(), 'wf-1', false)

    expect(result.error).toEqual({ message: 'Access denied', status: 403 })
  })
})
