import type { Tool, ToolExecutionOptions } from '../types'
import { serviceUnavailable } from '../types'
import type { CreateScheduleInput, AbsoluteScheduleConfig } from '../../../scheduler/types'
import { getToolServices } from '../registry'
import type { SchedulerToolConfig } from './types'

/**
 * Create a scheduler tool that schedules future execution of agents/workflows
 *
 * Scheduler tools enable time-based automation by creating scheduled tasks that
 * execute at a specific time. The task contains the input payload and routes to
 * the specified resource.
 *
 * @param config - Configuration for the scheduler tool
 * @returns Tool that creates scheduled tasks
 *
 * @example
 * const schedulerTool = createSchedulerTool({
 *   name: 'schedule_followup',
 *   description: 'Schedule a follow-up task for later',
 *   inputSchema: z.object({ message: z.string(), recipientId: z.string() }),
 *   outputSchema: z.object({ taskId: z.string() }),
 *   targetResourceId: 'followup-agent',
 *   targetResourceType: 'agent',
 *   runAt: new Date(Date.now() + 86400000), // 24 hours from now
 *   maxRetries: 3
 * })
 */
export function createSchedulerTool(config: SchedulerToolConfig): Tool {
  return {
    name: config.name,
    description: config.description,
    inputSchema: config.inputSchema,
    outputSchema: config.outputSchema,

    async execute(options: ToolExecutionOptions): Promise<unknown> {
      // ExecutionContext is required for platform tools
      if (!options.executionContext) {
        throw serviceUnavailable('ExecutionContext', { tool: config.name, reason: 'organizationId required for multi-tenant isolation' })
      }

      // Get task scheduler service from global registry
      const { taskSchedulerService: taskScheduler } = getToolServices()
      if (!taskScheduler) {
        throw serviceUnavailable('TaskSchedulerService', {
          message: 'Ensure toolServicesRegistry.initialize() was called in apps/api/src/main.ts',
          tool: config.name
        })
      }

      // Convert simple runAt to AbsoluteScheduleConfig (single-item schedule)
      const scheduleConfig: AbsoluteScheduleConfig = {
        type: 'absolute',
        items: [{
          runAt: config.runAt.toISOString(),
          payload: options.input as Record<string, unknown>,
          label: config.taskDescription
        }]
      }

      // Build schedule input using execution context
      const scheduleInput: CreateScheduleInput = {
        organizationId: options.executionContext.organizationId,
        name: config.taskDescription ?? `Scheduled: ${config.name}`,
        description: `Created by ${config.name} tool`,
        target: {
          resourceType: config.targetResourceType,
          resourceId: config.targetResourceId
        },
        scheduleConfig,
        maxRetries: config.maxRetries ?? 3,
        idempotencyKey: config.idempotencyKey,

        // Origin tracking
        originExecutionId: options.executionContext.executionId,
        originResourceType: 'agent',
        originResourceId: options.executionContext.resourceId
      }

      // Create schedule (returns TaskSchedule)
      const schedule = await taskScheduler.createSchedule(scheduleInput)

      // Return schedule ID for tracking (unchanged return shape)
      return { taskId: schedule.id }
    }
  }
}
