/**
 * Unit tests for execution domain Zod validation schemas
 * Tests cover all schemas defined in api-schemas.ts
 *
 * Test Categories:
 * 1. External API schemas (CRITICAL - public-facing)
 * 2. Execution Engine schemas (CRITICAL - internal execution)
 * 3. Command Queue schemas (human-in-the-loop)
 * 4. Execution management schemas
 * 6. Attack scenario tests (security validation)
 */

import { describe, it, expect } from 'vitest'
import {
  ExternalExecuteRequestSchema,
  ExecutionEngineExecuteRequestSchema,
  ExecutionTargetSchema,
  OriginTrackingSchema,
  CreateCommandQueueTaskSchema,
  SubmitDecisionSchema,
  ListCommandQueueTasksSchema,
  ListExecutionsSchema,
  DeleteExecutionsSchema
} from '../api-schemas'

// Test UUIDs
const VALID_UUID = '550e8400-e29b-41d4-a716-446655440000'
const VALID_UUID_2 = '550e8400-e29b-41d4-a716-446655440001'
const _INVALID_UUID = 'not-a-uuid'

describe('ExternalExecuteRequestSchema', () => {
  it('accepts valid request with object input', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID,
      input: { message: 'Hello', data: { value: 123 } }
    })
    expect(result.success).toBe(true)
  })

  it('accepts valid request with string input', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID,
      input: 'Simple string input'
    })
    expect(result.success).toBe(true)
  })

  it('accepts valid request with array input', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID,
      input: [1, 2, 3, { nested: 'object' }]
    })
    expect(result.success).toBe(true)
  })

  it('rejects empty string resourceId', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: '',
      input: {}
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].path).toContain('resourceId')
    }
  })

  it('accepts non-UUID string resourceId (kebab-case names allowed)', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: 'my-workflow-name',
      input: {}
    })
    expect(result.success).toBe(true)
  })

  it('rejects payload exceeding 500KB size limit', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID,
      input: 'x'.repeat(600_000) // Exceeds 500KB
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].message).toContain('exceeds maximum size')
    }
  })

  it('rejects additional fields (strict mode - organizationId injection)', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID,
      input: {},
      organizationId: 'malicious-org-id' // Should be blocked by strict mode
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].code).toBe('unrecognized_keys')
    }
  })

  it('rejects missing resourceId', () => {
    const result = ExternalExecuteRequestSchema.safeParse({
      input: {}
    })
    expect(result.success).toBe(false)
  })

  it('accepts missing input (some workflows do not need input)', () => {
    // Note: input field allows undefined - some workflows don't require input
    const result = ExternalExecuteRequestSchema.safeParse({
      resourceId: VALID_UUID
      // missing input field - this is acceptable
    })
    expect(result.success).toBe(true)
  })
})

describe('ExecutionEngineExecuteRequestSchema', () => {
  it('accepts valid workflow execution with input', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow',
      resourceId: 'linear-test-workflow',
      input: { data: 'test' }
    })
    expect(result.success).toBe(true)
  })

  it('accepts valid agent execution without input', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'agent',
      resourceId: 'basic-agent'
    })
    expect(result.success).toBe(true)
  })

  it('accepts valid execution with undefined input', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow',
      resourceId: 'my-workflow',
      input: undefined
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid resource type', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'malicious',
      resourceId: 'some-workflow'
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].path).toContain('resourceType')
      // Zod v4 message: "Invalid option: expected one of..."
      expect(issues[0].message).toMatch(/Invalid (enum value|option)/)
    }
  })

  it('accepts kebab-case resource ID strings', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow',
      resourceId: 'linear-test-workflow'
    })
    expect(result.success).toBe(true)
  })

  it('rejects empty resource ID', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow',
      resourceId: ''
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].path).toContain('resourceId')
    }
  })

  it('rejects oversized input payload', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'agent',
      resourceId: 'test-agent',
      input: { data: 'x'.repeat(600_000) }
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      expect(issues[0].message).toContain('exceeds maximum size')
    }
  })

  it('rejects additional fields (strict mode)', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow',
      resourceId: 'test-workflow',
      input: {},
      organizationId: 'injected-org' // Should be blocked
    })
    expect(result.success).toBe(false)
  })

  it('rejects missing resourceType', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceId: 'test-workflow'
    })
    expect(result.success).toBe(false)
  })

  it('rejects missing resourceId', () => {
    const result = ExecutionEngineExecuteRequestSchema.safeParse({
      resourceType: 'workflow'
    })
    expect(result.success).toBe(false)
  })
})

describe('ExecutionTargetSchema', () => {
  it('accepts valid execution target', () => {
    const result = ExecutionTargetSchema.safeParse({
      resourceType: 'workflow',
      resourceId: VALID_UUID,
      payload: { key: 'value' }
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid resource type', () => {
    const result = ExecutionTargetSchema.safeParse({
      resourceType: 'invalid',
      resourceId: VALID_UUID,
      payload: {}
    })
    expect(result.success).toBe(false)
  })

  it('accepts non-UUID resource ID (workflow/agent names)', () => {
    const result = ExecutionTargetSchema.safeParse({
      resourceType: 'agent',
      resourceId: 'my-agent-name',
      payload: {}
    })
    expect(result.success).toBe(true)
  })

  it('rejects payload exceeding size limit', () => {
    const result = ExecutionTargetSchema.safeParse({
      resourceType: 'agent',
      resourceId: VALID_UUID,
      payload: { data: 'x'.repeat(600_000) }
    })
    expect(result.success).toBe(false)
  })

  it('accepts missing payload (allows undefined for workflows without input)', () => {
    // Some workflows/agents don't require input payload
    const result = ExecutionTargetSchema.safeParse({
      resourceType: 'workflow',
      resourceId: VALID_UUID
      // Missing payload is acceptable
    })
    expect(result.success).toBe(true)
  })
})

describe('OriginTrackingSchema', () => {
  it('accepts valid origin tracking', () => {
    const result = OriginTrackingSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'agent',
      originResourceId: 'approval-agent'
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid origin execution UUID', () => {
    const result = OriginTrackingSchema.safeParse({
      originExecutionId: 'not-uuid',
      originResourceType: 'workflow',
      originResourceId: 'test-workflow'
    })
    expect(result.success).toBe(false)
  })

  it('rejects invalid origin resource type', () => {
    const result = OriginTrackingSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'invalid',
      originResourceId: 'test'
    })
    expect(result.success).toBe(false)
  })

  it('rejects oversized origin resource ID', () => {
    const result = OriginTrackingSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'scheduler',
      originResourceId: 'x'.repeat(150) // Exceeds 100 char max
    })
    expect(result.success).toBe(false)
  })
})

describe('CreateCommandQueueTaskSchema', () => {
  it('accepts valid task creation with all fields', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'agent',
      originResourceId: 'approval-agent',
      approveTarget: {
        resourceType: 'workflow',
        resourceId: VALID_UUID_2,
        payload: { approved: true }
      },
      rejectTarget: {
        resourceType: 'workflow',
        resourceId: VALID_UUID,
        payload: { rejected: true }
      },
      payloadInitial: { request: 'approval needed' },
      description: 'Test approval task',
      priority: 5,
      expiresAt: '2025-12-31T23:59:59Z'
    })
    expect(result.success).toBe(true)
  })

  it('accepts valid task creation with minimal fields', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'workflow',
      originResourceId: 'test-workflow',
      approveTarget: {
        resourceType: 'agent',
        resourceId: VALID_UUID,
        payload: {}
      },
      payloadInitial: {}
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid origin UUID', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: 'not-uuid',
      originResourceType: 'agent',
      originResourceId: 'test',
      approveTarget: {
        resourceType: 'workflow',
        resourceId: VALID_UUID,
        payload: {}
      },
      payloadInitial: {}
    })
    expect(result.success).toBe(false)
  })

  it('rejects invalid priority (out of range)', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'api',
      originResourceId: 'external-api',
      approveTarget: {
        resourceType: 'workflow',
        resourceId: VALID_UUID,
        payload: {}
      },
      payloadInitial: {},
      priority: 15 // Max is 10
    })
    expect(result.success).toBe(false)
  })

  it('rejects oversized description', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'scheduler',
      originResourceId: 'task-scheduler',
      approveTarget: {
        resourceType: 'agent',
        resourceId: VALID_UUID,
        payload: {}
      },
      payloadInitial: {},
      description: 'x'.repeat(1500) // Exceeds 1000 char limit
    })
    expect(result.success).toBe(false)
  })

  it('rejects invalid nested target', () => {
    const result = CreateCommandQueueTaskSchema.safeParse({
      originExecutionId: VALID_UUID,
      originResourceType: 'agent',
      originResourceId: 'test',
      approveTarget: {
        resourceType: 'invalid', // Invalid enum
        resourceId: VALID_UUID,
        payload: {}
      },
      payloadInitial: {}
    })
    expect(result.success).toBe(false)
  })
})

describe('SubmitDecisionSchema', () => {
  it('accepts approve decision with notes', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'approve',
      notes: 'Looks good to proceed'
    })
    expect(result.success).toBe(true)
  })

  it('accepts reject decision with payload override', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'reject',
      notes: 'Missing required data',
      payloadOverride: { reason: 'incomplete' }
    })
    expect(result.success).toBe(true)
  })

  it('accepts decision without notes', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'approve'
    })
    expect(result.success).toBe(true)
  })

  it('rejects invalid decision value', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'maybe'
    })
    expect(result.success).toBe(false)
    if (!result.success) {
      const issues = result.error.issues || result.error.errors || []
      expect(issues.length).toBeGreaterThan(0)
      // Zod v4 message: "Invalid option: expected one of..."
      expect(issues[0].message).toMatch(/Invalid (enum value|option)/)
    }
  })

  it('rejects oversized notes', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'reject',
      notes: 'x'.repeat(6000) // Exceeds 5000 char limit
    })
    expect(result.success).toBe(false)
  })

  it('rejects oversized payload override', () => {
    const result = SubmitDecisionSchema.safeParse({
      decision: 'approve',
      payloadOverride: { data: 'x'.repeat(600_000) }
    })
    expect(result.success).toBe(false)
  })
})

describe('ListCommandQueueTasksSchema', () => {
  it('accepts valid status filter', () => {
    const result = ListCommandQueueTasksSchema.safeParse({
      status: 'pending',
      limit: 50
    })
    expect(result.success).toBe(true)
  })

  it('accepts no filters (defaults applied)', () => {
    const result = ListCommandQueueTasksSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.limit).toBe(20) // Default value
    }
  })

  it('rejects invalid status', () => {
    const result = ListCommandQueueTasksSchema.safeParse({
      status: 'invalid'
    })
    expect(result.success).toBe(false)
  })

  it('rejects limit exceeding maximum', () => {
    const result = ListCommandQueueTasksSchema.safeParse({
      limit: 200 // Max is 100
    })
    expect(result.success).toBe(false)
  })
})

describe('ListExecutionsSchema', () => {
  it('accepts valid status filter', () => {
    const result = ListExecutionsSchema.safeParse({
      resourceStatus: 'prod'
    })
    expect(result.success).toBe(true)
  })

  it('accepts no filter (default applied)', () => {
    const result = ListExecutionsSchema.safeParse({})
    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.resourceStatus).toBe('all')
    }
  })

  it('rejects invalid status', () => {
    const result = ListExecutionsSchema.safeParse({
      resourceStatus: 'invalid'
    })
    expect(result.success).toBe(false)
  })
})

describe('DeleteExecutionsSchema', () => {
  it('accepts valid status filter', () => {
    const result = DeleteExecutionsSchema.safeParse({
      resourceStatus: 'dev'
    })
    expect(result.success).toBe(true)
  })

  it('accepts no filter', () => {
    const result = DeleteExecutionsSchema.safeParse({})
    expect(result.success).toBe(true)
  })

  it('rejects "all" as status (only dev/prod allowed)', () => {
    const result = DeleteExecutionsSchema.safeParse({
      resourceStatus: 'all'
    })
    expect(result.success).toBe(false)
  })
})

// ============================================================================
// ATTACK SCENARIO TESTS (SECURITY VALIDATION)
// ============================================================================

describe('Attack Scenarios', () => {
  describe('ResourceId Security', () => {
    it('accepts path-like strings (security handled at DB layer, not schema)', () => {
      // Note: resourceId is a non-empty string (workflow/agent name)
      // Path traversal, SQL injection, command injection are ALL prevented at the
      // database layer via parameterized queries, not at schema validation
      const result = ExternalExecuteRequestSchema.safeParse({
        resourceId: '../../etc/passwd',
        input: {}
      })
      // Schema accepts any non-empty string; DB lookup will find no matching resource
      expect(result.success).toBe(true)
    })

    it('accepts SQL/command injection strings (security handled at DB layer)', () => {
      // Note: resourceId is a string (workflow/agent name), not executed as SQL/shell command
      // SQL injection: Prevented by parameterized queries in database layer
      // Command injection: resourceId is never executed as shell command
      const sqlResult = ExecutionEngineExecuteRequestSchema.safeParse({
        resourceType: 'workflow',
        resourceId: "' OR '1'='1" // Valid workflow name (strange but technically valid)
      })
      expect(sqlResult.success).toBe(true)

      const cmdResult = ExecutionEngineExecuteRequestSchema.safeParse({
        resourceType: 'agent',
        resourceId: '$(rm -rf /)' // Valid agent name (strange but technically valid)
      })
      expect(cmdResult.success).toBe(true)
    })
  })

  describe('Payload Size DoS Attacks', () => {
    it('blocks 1MB payload in External API', () => {
      const result = ExternalExecuteRequestSchema.safeParse({
        resourceId: VALID_UUID,
        input: { data: 'x'.repeat(1_000_000) }
      })
      expect(result.success).toBe(false)
    })

    it('blocks 10MB payload in Execution Engine', () => {
      const result = ExecutionEngineExecuteRequestSchema.safeParse({
        resourceType: 'workflow',
        resourceId: VALID_UUID,
        input: { largeArray: Array(10_000_000).fill('x') }
      })
      expect(result.success).toBe(false)
    })
  })

  describe('organizationId Injection Attacks (Strict Mode)', () => {
    it('blocks organizationId in External API request', () => {
      const result = ExternalExecuteRequestSchema.safeParse({
        resourceId: VALID_UUID,
        input: {},
        organizationId: 'victim-org-id'
      })
      expect(result.success).toBe(false)
      if (!result.success) {
        const issues = result.error.issues || result.error.errors || []
        expect(issues.length).toBeGreaterThan(0)
        expect(issues[0].code).toBe('unrecognized_keys')
      }
    })

    it('blocks organizationId in Execution Engine request', () => {
      const result = ExecutionEngineExecuteRequestSchema.safeParse({
        resourceType: 'workflow',
        resourceId: VALID_UUID,
        input: {},
        organizationId: 'victim-org-id'
      })
      expect(result.success).toBe(false)
    })

    it('blocks organizationId in command queue task', () => {
      const result = CreateCommandQueueTaskSchema.safeParse({
        originExecutionId: VALID_UUID,
        originResourceType: 'agent',
        originResourceId: 'test',
        approveTarget: {
          resourceType: 'workflow',
          resourceId: VALID_UUID,
          payload: {}
        },
        payloadInitial: {},
        organizationId: 'injected-org'
      })
      expect(result.success).toBe(false)
    })
  })

  describe('Field Injection Attacks', () => {
    it('blocks arbitrary field injection', () => {
      const result = ExternalExecuteRequestSchema.safeParse({
        resourceId: VALID_UUID,
        input: {},
        adminOverride: true,
        privileged: 'yes'
      })
      expect(result.success).toBe(false)
    })

    it('blocks nested field injection in execution target', () => {
      const result = CreateCommandQueueTaskSchema.safeParse({
        originExecutionId: VALID_UUID,
        originResourceType: 'agent',
        originResourceId: 'test',
        approveTarget: {
          resourceType: 'workflow',
          resourceId: VALID_UUID,
          payload: {},
          adminBypass: true // Extra field in nested object
        },
        payloadInitial: {}
      })
      expect(result.success).toBe(false)
    })
  })
})
