/**
 * Zod schema for runtime validation of workflows
 * Updated for flexible stack system
 */

import { z } from 'zod';

// Actor schema
const ActorSchema = z.object({
  type: z.string(),
  role: z.string(),
});

// Workflow relationship schema
const WorkflowRelationshipSchema = z.object({
  workflow: z.string(),
  type: z.enum(['prerequisite', 'dependent', 'related']),
  reason: z.string(),
});

// Workflow config schema
const WorkflowConfigSchema = z.object({
  packageManager: z.enum(['npm', 'yarn', 'pnpm', 'bun']).optional(),
  nodeVersion: z.string().optional(),
}).passthrough(); // Allow additional config options

// Workflow metadata schema
const WorkflowMetadataSchema = z.object({
  id: z.string().min(1, 'Workflow ID is required - use a unique identifier like "user-authentication" or "task-management"'),
  version: z.string().min(1, 'Version is required - use semantic versioning like "1.0.0"'),
  name: z.string().min(1, 'Name is required - provide a human-readable name for your workflow'),
  description: z.string().min(1, 'Description is required - explain what this workflow does'),
  domains: z.array(z.string()).optional(),
  actors: z.array(ActorSchema).optional(),
  relationships: z.array(WorkflowRelationshipSchema).optional(),
  config: WorkflowConfigSchema.optional(),
});

// Validation rule schema
const ValidationRuleSchema = z.object({
  required: z.boolean().optional(),
  format: z.string().optional(),
  minLength: z.number().optional(),
  maxLength: z.number().optional(),
  pattern: z.string().optional(),
  custom: z.string().optional(),
});

// Field schema
const FieldSchema = z.object({
  id: z.string(),
  type: z.string(),
  label: z.string(),
  placeholder: z.string().optional(),
  validation: z.array(ValidationRuleSchema).optional(),
});

// UI spec schema
const UISpecSchema = z.object({
  layout: z.string().optional(),
  fields: z.array(FieldSchema).optional(),
});

// State definition schema
const StateDefinitionSchema = z.object({
  name: z.string(),
  type: z.string(),
  initial: z.any(),
});

// Step schema (flexible to support different action types)
const StepSchema = z.object({
  id: z.string(),
  action: z.string(),
  depends_on: z.array(z.string()).optional(),
}).passthrough(); // Allow additional properties

// Action schema
const ActionSchema = z.object({
  id: z.string(),
  trigger: z.string(),
  description: z.string().optional(), // Optional - can be inferred from id
  steps: z.array(StepSchema).optional(), // Optional - if not provided, generates scaffold only
});

// Generate options schema
const GenerateOptionsSchema = z.object({
  styling: z.string().optional(),
  testing: z.boolean().optional(),
  storybook: z.boolean().optional(),
  accessibility: z.string().optional(),
});

// Component schema (for UI components)
const ComponentSchema = z.object({
  id: z.string(),
  type: z.string().optional(), // Optional - can be inferred from parent context
  name: z.string(),
  description: z.string().optional(), // Optional - can be minimal scaffold
  ui: UISpecSchema.optional(),
  state: z.array(StateDefinitionSchema).optional(),
  actions: z.array(ActionSchema).optional(),
  generate: GenerateOptionsSchema.optional(),
});

// Property schema
const PropertySchemaSchema = z.object({
  type: z.string(),
  format: z.string().optional(),
  description: z.string().optional(),
  example: z.any().optional(),
  enum: z.array(z.any()).optional(),
});

// Schema schema (for request/response bodies)
const SchemaSchema: z.ZodType<any> = z.lazy(() =>
  z.object({
    type: z.string(),
    required: z.array(z.string()).optional(),
    properties: z.record(PropertySchemaSchema).optional(),
  })
);

// Request spec schema
const RequestSpecSchema = z.object({
  body: SchemaSchema.optional(),
  query: SchemaSchema.optional(),
  params: SchemaSchema.optional(),
  headers: SchemaSchema.optional(),
});

// Response spec schema
const ResponseSpecSchema = z.object({
  status: z.number(),
  description: z.string(),
  body: SchemaSchema.optional(),
});

// Implementation schema
const ImplementationSchema = z.object({
  steps: z.array(StepSchema),
});

// Middleware schema
const MiddlewareSchema = z.record(z.any());

// Endpoint schema (for API endpoints)
const EndpointSchema = z.object({
  id: z.string(),
  path: z.string(),
  method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']),
  name: z.string(),
  description: z.string(),
  request: RequestSpecSchema.optional(),
  responses: z.array(ResponseSpecSchema),
  implementation: ImplementationSchema.optional(),
  middleware: z.array(MiddlewareSchema).optional(),
  generate: GenerateOptionsSchema.optional(),
});

// Field definition schema (for database tables)
const FieldDefinitionSchema = z.object({
  name: z.string(),
  type: z.string(),
  primary_key: z.boolean().optional(),
  unique: z.boolean().optional(),
  indexed: z.boolean().optional(),
  foreign_key: z.string().optional(),
  nullable: z.boolean().optional(),
  default: z.any().optional(),
});

// Table schema (for database)
const TableSchema = z.object({
  name: z.string(),
  description: z.string(),
  required_fields: z.array(FieldDefinitionSchema),
});

// Component workflow schema
const ComponentWorkflowSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string(),
  steps: z.array(StepSchema),
});

// CLI Command Argument schema
const CommandArgumentSchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  required: z.boolean().optional(),
  default: z.any().optional(),
});

// CLI Command Option schema
const CommandOptionSchema = z.object({
  name: z.string(),
  alias: z.string().optional(),
  description: z.string().optional(),
  type: z.string().optional(),
});

// CLI Command schema
const CommandSchema = z.object({
  id: z.string(),
  name: z.string().optional(),
  description: z.string().optional(),
  arguments: z.array(CommandArgumentSchema).optional(),
  options: z.array(CommandOptionSchema).optional(),
  implementation: ImplementationSchema.optional(),
});

// Expected dependency schema (for version management)
const ExpectedDependencySchema = z.object({
  service: z.string(),
  usage: z.string(),
  required: z.boolean().optional(),
});

// Stack Component schema - flexible, can contain different things based on type
const StackComponentSchema = z.object({
  type: z.string({ required_error: 'Stack component type is required - use "frontend", "backend", "database", etc.' }), // completely customizable
  technology: z.string({ required_error: 'Technology is required - specify the framework or tool to use (e.g., "react", "express", "prisma")' }),
  description: z.string().optional(),
  config: z.record(z.any()).optional(),
  dependsOn: z.array(z.string()).optional(),
  components: z.array(ComponentSchema).optional(), // For frontend-like components
  endpoints: z.array(EndpointSchema).optional(), // For backend-like components
  tables: z.array(TableSchema).optional(), // For database-like components
  workflows: z.array(ComponentWorkflowSchema).optional(), // Component-specific workflows
  commands: z.array(CommandSchema).optional(), // For CLI components
  // Service routing configuration
  routing: z.enum(['primary_only', 'context_based', 'load_balanced']).optional(),
  primary: z.string().optional(),
  services: z.record(z.any()).optional(), // Service configurations with routing, weights, etc.
  // Version management
  expected_dependencies: z.array(ExpectedDependencySchema).optional(),
});

// Stack components - keyed by component name
const StackComponentsSchema = z.record(StackComponentSchema);

// Code example schema
const CodeExampleSchema = z.object({
  language: z.string(),
  code: z.string(),
});

// Doc content schema
const DocContentSchema = z.object({
  heading: z.string(),
  content: z.string(),
  steps: z.array(z.string()).optional(),
  examples: z.array(CodeExampleSchema).optional(),
});

// Doc section schema
const DocSectionSchema = z.object({
  title: z.string(),
  sections: z.array(DocContentSchema),
});

// Documentation schema
const DocumentationSchema = z.object({
  user_docs: z.array(DocSectionSchema).optional(),
  developer_docs: z.array(DocSectionSchema).optional(),
});

// Unit test schema
const UnitTestSchema = z.object({
  component: z.string(),
  scenarios: z.array(z.string()),
});

// Integration test schema
const IntegrationTestSchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  steps: z.array(z.string()),
});

// E2E test schema
const E2ETestSchema = z.object({
  name: z.string(),
  tool: z.string(),
  steps: z.array(z.string()),
});

// Testing schema
const _TestingSchema = z.object({
  unit_tests: z.array(UnitTestSchema).optional(),
  integration_tests: z.array(IntegrationTestSchema).optional(),
  e2e_tests: z.array(E2ETestSchema).optional(),
});

// Environment config schema - now keyed by component name
const EnvironmentConfigSchema = z.record(z.record(z.string()));

// Environment schema
const EnvironmentSchema = z.record(EnvironmentConfigSchema);

// Health check schema
const HealthCheckSchema = z.object({
  path: z.string(),
  interval: z.string().optional(),
});

// Deployment config schema
const DeploymentConfigSchema = z.object({
  build_command: z.string().optional(),
  start_command: z.string().optional(),
  output_directory: z.string().optional(),
  health_check: HealthCheckSchema.optional(),
  environment_variables: z.array(z.string()).optional(),
});

// Deployment schema - now keyed by component name
const _DeploymentSchema = z.record(DeploymentConfigSchema);

// Service instance schema (for infrastructure services)
const ServiceInstanceSchema = z.object({
  provider: z.string(),
  connection: z.string(),
  config: z.record(z.any()).optional(),
});

// Worker config schema
const WorkerConfigSchema = z.object({
  enabled: z.boolean().optional(),
  concurrency: z.number().optional(),
  queues: z.array(z.string()).optional(),
  config: z.record(z.any()).optional(),
});

// Stage config schema
const StageConfigSchema = z.object({
  log_level: z.enum(['debug', 'info', 'warn', 'error']).optional(),
  development_tools: z.boolean().optional(),
  error_details: z.boolean().optional(),
  cors: z.object({
    enabled: z.boolean().optional(),
    origins: z.array(z.string()).optional(),
  }).optional(),
  rate_limiting: z.object({
    enabled: z.boolean().optional(),
    requests_per_minute: z.number().optional(),
  }).optional(),
  custom: z.record(z.any()).optional(),
});

// Stage infrastructure schema
const StageInfrastructureSchema = z.object({
  domains: z.object({
    web: z.string().optional(),
    api: z.string().optional(),
    docs: z.string().optional(),
    portal: z.string().optional(),
    admin: z.string().optional(),
    marketing: z.string().optional(),
    custom: z.record(z.string()).optional(),
  }).optional(),
  databases: z.object({
    primary: z.string(),
    analytics: z.string().optional(),
    cache: z.string().optional(),
    custom: z.record(z.string()).optional(),
  }),
  services: z.object({
    redis: ServiceInstanceSchema.optional(),
    queue: ServiceInstanceSchema.optional(),
    storage: ServiceInstanceSchema.optional(),
    search: ServiceInstanceSchema.optional(),
    email: ServiceInstanceSchema.optional(),
    cdn: ServiceInstanceSchema.optional(),
    monitoring: ServiceInstanceSchema.optional(),
    custom: z.record(ServiceInstanceSchema).optional(),
  }).optional(),
  workers: WorkerConfigSchema.optional(),
});

// Stage schema
const StageSchema = z.object({
  description: z.string().optional(),
  infrastructure: StageInfrastructureSchema,
  config: StageConfigSchema.optional(),
  env: z.record(z.string()).optional(),
});

// Stages schema - keyed by stage name
const StagesSchema = z.record(StageSchema);

// ===== ENHANCED SCHEMA: Cross-Cutting Concerns =====

// Technology configuration
const TechnologySchema = z.object({
  backend: z.object({
    framework: z.string().optional(),
    language: z.string().optional(),
  }).optional(),
  frontend: z.object({
    framework: z.string().optional(),
    styling: z.string().optional(),
  }).optional(),
  database: z.string().optional(),
}).passthrough();

// Testing framework configuration
const TestFrameworkConfigSchema = z.object({
  tool: z.enum(['vitest', 'jest', 'mocha', 'ava']).optional(),
  config: z.record(z.any()).optional(),
  pattern: z.string().optional(),
}).passthrough();

const E2ETestConfigSchema = z.object({
  tool: z.enum(['playwright', 'cypress', 'puppeteer']).optional(),
  config: z.record(z.any()).optional(),
  browsers: z.array(z.string()).optional(),
}).passthrough();

const CoverageThresholdSchema = z.object({
  statements: z.number().optional(),
  branches: z.number().optional(),
  functions: z.number().optional(),
  lines: z.number().optional(),
});

const ExternalApiMockSchema = z.object({
  service: z.string(),
  base_url: z.string(),
  handlers: z.array(z.string()).optional(),
});

const TestFixturesSchema = z.object({
  path: z.string().optional(),
  auto_load: z.boolean().optional(),
});

const FactoryConfigSchema = z.object({
  tool: z.enum(['faker', 'fishery', 'factory_bot']).optional(),
  path: z.string().optional(),
});

// Enhanced Testing schema
const EnhancedTestingSchema = z.object({
  frameworks: z.object({
    unit: TestFrameworkConfigSchema.optional(),
    integration: TestFrameworkConfigSchema.optional(),
    e2e: E2ETestConfigSchema.optional(),
    component: TestFrameworkConfigSchema.optional(),
  }).optional(),
  coverage: z.object({
    threshold: z.object({
      global: CoverageThresholdSchema.optional(),
      per_file: CoverageThresholdSchema.optional(),
    }).optional(),
    exclude: z.array(z.string()).optional(),
  }).optional(),
  database: z.object({
    strategy: z.enum(['testcontainers', 'sqlite', 'dedicated', 'mock']),
    reset_strategy: z.enum(['truncate', 'drop_and_recreate']).optional(),
    fixtures_path: z.string().optional(),
  }).optional(),
  workers: z.object({
    strategy: z.enum(['mock_queue', 'test_redis', 'in_memory']),
    auto_process: z.boolean().optional(),
  }).optional(),
  external_apis: z.object({
    strategy: z.enum(['msw', 'nock', 'mock_server']),
    handlers_path: z.string().optional(),
    mock_definitions: z.array(ExternalApiMockSchema).optional(),
  }).optional(),
  ci_cd: z.object({
    provider: z.enum(['github_actions', 'gitlab_ci', 'circle_ci']).optional(),
    test_on_pr: z.boolean().optional(),
    test_requirements: z.object({
      require_passing: z.boolean().optional(),
      minimum_coverage: z.number().optional(),
    }).optional(),
  }).optional(),
  fixtures: TestFixturesSchema.optional(),
  factories: FactoryConfigSchema.optional(),
  // Legacy format support
  unit_tests: z.array(UnitTestSchema).optional(),
  integration_tests: z.array(IntegrationTestSchema).optional(),
  e2e_tests: z.array(E2ETestSchema).optional(),
}).passthrough();

// Monitoring configuration
const LogTransportSchema = z.object({
  type: z.enum(['console', 'file', 'http', 'syslog']),
  config: z.record(z.any()).optional(),
});

const MetricDefinitionSchema = z.object({
  name: z.string(),
  type: z.enum(['counter', 'gauge', 'histogram']),
  description: z.string().optional(),
});

const AlertDefinitionSchema = z.object({
  name: z.string(),
  condition: z.string(),
  severity: z.enum(['low', 'medium', 'high', 'critical']),
  channels: z.array(z.string()).optional(),
});

const MonitoringSchema = z.object({
  apm: z.object({
    provider: z.string(),
    config: z.record(z.any()).optional(),
  }).optional(),
  error_tracking: z.object({
    provider: z.string(),
    config: z.record(z.any()).optional(),
    frontend: z.boolean().optional(),
    backend: z.boolean().optional(),
  }).optional(),
  logging: z.object({
    provider: z.string(),
    level: z.enum(['debug', 'info', 'warn', 'error']),
    transports: z.array(LogTransportSchema).optional(),
  }).optional(),
  tracing: z.object({
    provider: z.string(),
    sampling_rate: z.number().optional(),
  }).optional(),
  metrics: z.object({
    tracked: z.array(z.string()),
    custom_metrics: z.array(MetricDefinitionSchema).optional(),
  }).optional(),
  alerts: z.array(AlertDefinitionSchema).optional(),
}).passthrough();

// Security configuration
const DataRetentionPolicySchema = z.object({
  user_data: z.string().optional(),
  logs: z.string().optional(),
  backups: z.string().optional(),
});

const GDPRConfigSchema = z.object({
  data_export: z.boolean().optional(),
  right_to_be_forgotten: z.boolean().optional(),
  consent_management: z.boolean().optional(),
});

const RateLimitingConfigSchema = z.object({
  enabled: z.boolean(),
  default_limit: z.string().optional(),
  per_endpoint: z.record(z.string()).optional(),
});

const SecuritySchema = z.object({
  compliance: z.object({
    regulations: z.array(z.enum(['gdpr', 'ccpa', 'hipaa', 'soc2', 'pci_dss'])),
    data_retention: DataRetentionPolicySchema.optional(),
    gdpr: GDPRConfigSchema.optional(),
  }).optional(),
  encryption: z.object({
    at_rest: z.boolean(),
    in_transit: z.boolean(),
    field_level: z.array(z.string()).optional(),
  }).optional(),
  audit_logging: z.object({
    enabled: z.boolean(),
    retention: z.string(),
    log_all_database_changes: z.boolean().optional(),
    log_api_requests: z.boolean().optional(),
  }).optional(),
  csp: z.object({
    enabled: z.boolean(),
    directives: z.record(z.array(z.string())).optional(),
  }).optional(),
  rate_limiting: RateLimitingConfigSchema.optional(),
}).passthrough();

// Performance configuration
const PerformanceSchema = z.object({
  frontend: z.object({
    code_splitting: z.enum(['route_based', 'component_based', 'manual']).optional(),
    lazy_loading: z.boolean().optional(),
    tree_shaking: z.boolean().optional(),
    bundle_budget: z.object({
      max_initial: z.string().optional(),
      max_total: z.string().optional(),
    }).optional(),
  }).optional(),
  backend: z.object({
    caching: z.object({
      strategy: z.enum(['redis', 'memcached', 'in_memory']),
      ttl: z.number().optional(),
      cache_keys: z.array(z.string()).optional(),
    }).optional(),
    connection_pooling: z.object({
      min: z.number(),
      max: z.number(),
      idle_timeout: z.number().optional(),
    }).optional(),
    query_optimization: z.boolean().optional(),
  }).optional(),
  database: z.object({
    read_replicas: z.number().optional(),
    sharding: z.object({
      strategy: z.enum(['by_tenant', 'by_date', 'by_hash']),
      shard_count: z.number().optional(),
    }).optional(),
    indexing_strategy: z.enum(['auto', 'manual']).optional(),
  }).optional(),
  cdn: z.object({
    provider: z.string(),
    assets: z.array(z.string()).optional(),
    cache_ttl: z.number().optional(),
  }).optional(),
}).passthrough();

// Internationalization configuration
const InternationalizationSchema = z.object({
  default_locale: z.string(),
  supported_locales: z.array(z.string()),
  translation_files: z.string().optional(),
  fallback_strategy: z.enum(['cascade', 'default']).optional(),
  formatting: z.object({
    dates: z.enum(['locale_specific', 'iso']).optional(),
    numbers: z.enum(['locale_specific', 'standard']).optional(),
    currency: z.enum(['locale_specific', 'usd']).optional(),
  }).optional(),
  translation_management: z.object({
    provider: z.string().optional(),
    auto_sync: z.boolean().optional(),
  }).optional(),
}).passthrough();

// Feature flags configuration
const FeatureFlagsSchema = z.object({
  provider: z.string(),
  flags: z.array(z.object({
    name: z.string(),
    enabled: z.boolean(),
    rollout_percentage: z.number().optional(),
    rollout_strategy: z.enum(['gradual', 'immediate']).optional(),
    targeting: z.object({
      user_segments: z.array(z.string()).optional(),
    }).optional(),
    schedule: z.array(z.object({
      date: z.string(),
      percentage: z.number(),
    })).optional(),
  })).optional(),
}).passthrough();

// Access control configuration
const AccessControlSchema = z.object({
  model: z.enum(['rbac', 'abac', 'rbac_with_abac']),
  roles: z.array(z.object({
    name: z.string(),
    permissions: z.array(z.object({
      resource: z.string(),
      actions: z.array(z.string()),
      conditions: z.array(z.object({
        field: z.string(),
        operator: z.enum(['equals', 'contains', 'gt', 'lt']),
        value: z.any(),
      })).optional(),
    })),
  })).optional(),
  policies: z.array(z.object({
    name: z.string(),
    resource: z.string(),
    action: z.string(),
    rules: z.array(z.object({
      role: z.string().optional(),
      condition: z.string().optional(),
    })),
  })).optional(),
}).passthrough();

// API configuration
const ApiConfigurationSchema = z.object({
  base_path: z.string().optional(),
  documentation: z.object({
    format: z.enum(['openapi', 'swagger', 'graphql_schema']),
    auto_generate: z.boolean(),
    output: z.string().optional(),
  }).optional(),
  versioning: z.object({
    strategy: z.enum(['url_path', 'header', 'query_param']),
    deprecation_policy: z.object({
      notice_period: z.string(),
      sunset_headers: z.boolean(),
    }).optional(),
  }).optional(),
  cors: z.object({
    enabled: z.boolean(),
    origins: z.array(z.string()).optional(),
    methods: z.array(z.string()).optional(),
    credentials: z.boolean().optional(),
  }).optional(),
  middleware: z.array(z.string()).optional(),
  endpoints: z.array(z.any()).optional(), // Complex Endpoint type
}).passthrough();

// Deployment configuration
const DeploymentConfigurationSchema = z.object({
  strategy: z.enum(['single_region', 'multi_region', 'edge']),
  regions: z.array(z.object({
    name: z.string(),
    primary: z.boolean().optional(),
    services: z.array(z.string()),
    database_replica: z.boolean().optional(),
  })).optional(),
  edge_functions: z.array(z.object({
    name: z.string(),
    regions: z.union([z.literal('all'), z.array(z.string())]),
    provider: z.string().optional(),
  })).optional(),
  geo_routing: z.object({
    enabled: z.boolean(),
    strategy: z.enum(['lowest_latency', 'closest_region', 'manual']),
  }).optional(),
  disaster_recovery: z.object({
    rpo: z.string(),
    rto: z.string(),
    replica_regions: z.array(z.string()).optional(),
    failover: z.enum(['automatic', 'manual']),
  }).optional(),
}).passthrough();

// Analytics configuration
const AnalyticsSchema = z.object({
  provider: z.string(),
  tracking: z.object({
    auto_track: z.array(z.string()).optional(),
    custom_events: z.array(z.object({
      name: z.string(),
      properties: z.array(z.string()),
    })).optional(),
  }).optional(),
  funnels: z.array(z.object({
    name: z.string(),
    steps: z.array(z.object({
      event: z.string(),
      required: z.boolean().optional(),
    })),
  })).optional(),
  cohorts: z.array(z.object({
    name: z.string(),
    criteria: z.string(),
  })).optional(),
}).passthrough();

// Models configuration (for data layer)
const ModelsSchema = z.record(z.any()).optional();

// Migrations configuration
const MigrationsSchema = z.object({
  tool: z.enum(['prisma', 'knex', 'typeorm', 'sequelize']).optional(),
  path: z.string().optional(),
}).passthrough().optional();

// Workflow definitions (business logic workflows)
const WorkflowDefinitionsSchema = z.record(z.any()).optional();

// Events configuration
const EventsSchema = z.record(z.any()).optional();

// Complete workflow schema with flexible stack and enhanced sections
export const WorkflowSchema = z.object({
  workflow: WorkflowMetadataSchema,
  technology: TechnologySchema.optional(),

  // === CROSS-CUTTING CONCERNS (Top-Level) ===
  testing: EnhancedTestingSchema.optional(),
  monitoring: MonitoringSchema.optional(),
  security: SecuritySchema.optional(),
  performance: PerformanceSchema.optional(),
  i18n: InternationalizationSchema.optional(),
  feature_flags: FeatureFlagsSchema.optional(),
  access_control: AccessControlSchema.optional(),
  api: ApiConfigurationSchema.optional(),
  deployment: DeploymentConfigurationSchema.optional(),
  analytics: AnalyticsSchema.optional(),

  // === COMPONENTS (Service-Specific) ===
  stack: StackComponentsSchema, // New flexible stack system

  // === DATA LAYER ===
  models: ModelsSchema,
  migrations: MigrationsSchema,

  // === BUSINESS LOGIC ===
  workflows: WorkflowDefinitionsSchema,
  events: EventsSchema,

  // === ENVIRONMENTS ===
  stages: StagesSchema.optional(), // Multi-stage infrastructure configuration

  // === LEGACY/OPTIONAL ===
  documentation: DocumentationSchema.optional(),
  environment: EnvironmentSchema.optional(),
}).refine(
  (data) => Object.keys(data.stack).length > 0,
  {
    message: 'Workflow must define at least one stack component (e.g., frontend, backend, database). Example: stack:\n  frontend:\n    type: frontend\n    technology: react',
  }
);

export type ValidatedWorkflow = z.infer<typeof WorkflowSchema>;
