import { Field, InputType, ObjectType, Int, Float, registerEnumType } from 'type-graphql'

/**
 * Labeling Workflow Scenario Types
 *
 * Defines end-to-end labeling workflows with multiple steps
 */

// ============================================================================
// Enums
// ============================================================================

export enum ScenarioStepType {
  ImportData = 'import_data',
  GeneratePredictions = 'generate_predictions',
  WaitForAnnotations = 'wait_for_annotations',
  SyncAnnotations = 'sync_annotations',
  ValidateQuality = 'validate_quality',
  ExportResults = 'export_results',
  Notification = 'notification'
}

registerEnumType(ScenarioStepType, {
  name: 'ScenarioStepType',
  description: 'Type of workflow step'
})

export enum ScenarioStatus {
  Draft = 'draft',
  Active = 'active',
  Paused = 'paused',
  Completed = 'completed',
  Failed = 'failed'
}

registerEnumType(ScenarioStatus, {
  name: 'ScenarioStatus',
  description: 'Status of workflow scenario'
})

export enum TriggerType {
  Manual = 'manual',
  Schedule = 'schedule',
  DatasetUpdate = 'dataset_update',
  ExternalEvent = 'external_event'
}

registerEnumType(TriggerType, {
  name: 'TriggerType',
  description: 'How the scenario is triggered'
})

// ============================================================================
// Scenario Step Types
// ============================================================================

@InputType()
export class ImportDataStepConfig {
  @Field({ description: 'Data source type: dataset, api, file' })
  sourceType: 'dataset' | 'api' | 'file'

  @Field({ nullable: true, description: 'DataSet ID if sourceType is dataset' })
  dataSetId?: string

  @Field({ nullable: true, description: 'External source URL if sourceType is api/file' })
  sourceUrl?: string

  @Field({ nullable: true, description: 'Image field name' })
  imageField?: string

  @Field({ nullable: true, description: 'Maximum items to import' })
  limit?: number
}

@InputType()
export class GeneratePredictionsStepConfig {
  @Field({ nullable: true, description: 'AI model ID to use' })
  modelId?: string

  @Field(type => Float, { nullable: true, description: 'Confidence threshold' })
  confidenceThreshold?: number

  @Field({ nullable: true, defaultValue: false, description: 'Force regenerate existing predictions' })
  forceRegenerate?: boolean
}

@InputType()
export class WaitForAnnotationsStepConfig {
  @Field(type => Int, { nullable: true, description: 'Minimum number of annotations required' })
  minAnnotations?: number

  @Field(type => Float, { nullable: true, description: 'Minimum completion rate (0-1)' })
  minCompletionRate?: number

  @Field(type => Int, { nullable: true, description: 'Maximum wait time in minutes' })
  maxWaitMinutes?: number

  @Field({ nullable: true, defaultValue: true, description: 'Auto-proceed when criteria met' })
  autoProceed?: boolean
}

@InputType()
export class SyncAnnotationsStepConfig {
  @Field({ nullable: true, defaultValue: true, description: 'Only sync completed annotations' })
  completedOnly?: boolean

  @Field({ nullable: true, description: 'Sync annotations updated after this date' })
  sinceDate?: Date
}

@InputType()
export class ValidateQualityStepConfig {
  @Field(type => Float, { nullable: true, description: 'Minimum required quality score (0-1)' })
  minQualityScore?: number

  @Field({ nullable: true, description: 'Validation rules in JSON format' })
  validationRules?: string
}

@InputType()
export class NotificationStepConfig {
  @Field({ description: 'Notification message template' })
  message: string

  @Field(type => [String], { nullable: true, description: 'Email recipients' })
  recipients?: string[]

  @Field({ nullable: true, description: 'Webhook URL to call' })
  webhookUrl?: string
}

// ============================================================================
// Scenario Step Definition
// ============================================================================

@InputType()
export class ScenarioStepInput {
  @Field({ description: 'Step name' })
  name: string

  @Field(type => ScenarioStepType, { description: 'Step type' })
  type: ScenarioStepType

  @Field({ description: 'Step configuration as JSON string' })
  config: string

  @Field({ nullable: true, description: 'Condition to execute this step (JSON logic)' })
  condition?: string

  @Field({ nullable: true, defaultValue: true, description: 'Continue on error' })
  continueOnError?: boolean

  @Field(type => Int, { nullable: true, description: 'Max retry attempts' })
  maxRetries?: number
}

@ObjectType()
export class ScenarioStep {
  @Field({ description: 'Step name' })
  name: string

  @Field(type => ScenarioStepType, { description: 'Step type' })
  type: ScenarioStepType

  @Field({ description: 'Step configuration' })
  config: string

  @Field({ nullable: true, description: 'Execution condition' })
  condition?: string

  @Field({ defaultValue: true, description: 'Continue on error' })
  continueOnError: boolean

  @Field(type => Int, { nullable: true, description: 'Max retry attempts' })
  maxRetries?: number

  @Field(type => Int, { description: 'Step order' })
  order: number
}

// ============================================================================
// Scenario Definition
// ============================================================================

@InputType()
export class CreateScenarioRequest {
  @Field({ description: 'Scenario name' })
  name: string

  @Field({ nullable: true, description: 'Scenario description' })
  description?: string

  @Field(type => Int, { description: 'Label Studio project ID' })
  projectId: number

  @Field(type => TriggerType, { description: 'How to trigger this scenario' })
  triggerType: TriggerType

  @Field({ nullable: true, description: 'Trigger configuration (schedule, event, etc.)' })
  triggerConfig?: string

  @Field(type => [ScenarioStepInput], { description: 'Workflow steps' })
  steps: ScenarioStepInput[]

  @Field({ nullable: true, defaultValue: true, description: 'Auto-start scenario after creation' })
  autoStart?: boolean
}

@ObjectType()
export class LabelingScenario {
  @Field({ description: 'Scenario ID' })
  id: string

  @Field({ description: 'Scenario name' })
  name: string

  @Field({ nullable: true, description: 'Description' })
  description?: string

  @Field(type => Int, { description: 'Label Studio project ID' })
  projectId: number

  @Field(type => TriggerType, { description: 'Trigger type' })
  triggerType: TriggerType

  @Field({ nullable: true, description: 'Trigger configuration' })
  triggerConfig?: string

  @Field(type => [ScenarioStep], { description: 'Workflow steps' })
  steps: ScenarioStep[]

  @Field(type => ScenarioStatus, { description: 'Current status' })
  status: ScenarioStatus

  @Field({ nullable: true, description: 'Last execution time' })
  lastExecutedAt?: Date

  @Field({ nullable: true, description: 'Next scheduled execution' })
  nextExecutionAt?: Date

  @Field({ description: 'Created at' })
  createdAt: Date

  @Field({ description: 'Updated at' })
  updatedAt: Date
}

// ============================================================================
// Scenario Execution
// ============================================================================

@InputType()
export class ExecuteScenarioRequest {
  @Field({ description: 'Scenario ID to execute' })
  scenarioId: string

  @Field({ nullable: true, description: 'Override parameters as JSON' })
  parameters?: string
}

@ObjectType()
export class ScenarioExecutionStep {
  @Field({ description: 'Step name' })
  stepName: string

  @Field(type => ScenarioStepType, { description: 'Step type' })
  stepType: ScenarioStepType

  @Field({ description: 'Step status: pending, running, completed, failed, skipped' })
  status: string

  @Field({ nullable: true, description: 'Step output data' })
  output?: string

  @Field({ nullable: true, description: 'Error message if failed' })
  error?: string

  @Field({ nullable: true, description: 'Started at' })
  startedAt?: Date

  @Field({ nullable: true, description: 'Completed at' })
  completedAt?: Date

  @Field(type => Int, { nullable: true, description: 'Duration in milliseconds' })
  durationMs?: number
}

@ObjectType()
export class ScenarioExecution {
  @Field({ description: 'Execution ID' })
  id: string

  @Field({ description: 'Scenario ID' })
  scenarioId: string

  @Field({ description: 'Scenario name' })
  scenarioName: string

  @Field({ description: 'Execution status: running, completed, failed' })
  status: string

  @Field(type => [ScenarioExecutionStep], { description: 'Step executions' })
  steps: ScenarioExecutionStep[]

  @Field({ nullable: true, description: 'Overall result summary' })
  summary?: string

  @Field({ description: 'Started at' })
  startedAt: Date

  @Field({ nullable: true, description: 'Completed at' })
  completedAt?: Date

  @Field(type => Int, { nullable: true, description: 'Total duration in milliseconds' })
  totalDurationMs?: number

  @Field({ nullable: true, description: 'Error message if failed' })
  error?: string
}

@ObjectType()
export class ScenarioExecutionResult {
  @Field({ description: 'Execution ID' })
  executionId: string

  @Field({ description: 'Execution status' })
  status: string

  @Field({ nullable: true, description: 'Execution summary' })
  summary?: string

  @Field({ nullable: true, description: 'Error if failed' })
  error?: string
}

// ============================================================================
// Scenario List and Status
// ============================================================================

@ObjectType()
export class LabelingScenarioList {
  @Field(type => [LabelingScenario], { description: 'List of scenarios' })
  items: LabelingScenario[]

  @Field(type => Int, { description: 'Total count' })
  total: number
}

@ObjectType()
export class ScenarioExecutionList {
  @Field(type => [ScenarioExecution], { description: 'List of executions' })
  items: ScenarioExecution[]

  @Field(type => Int, { description: 'Total count' })
  total: number
}

@InputType()
export class ScenarioStatusRequest {
  @Field({ description: 'Scenario ID' })
  scenarioId: string
}
