import { z } from 'zod'
import { ExecutionTargetSchema, OriginTrackingSchema } from '../core/api-schemas'
import {
  UuidSchema,
  NonEmptyStringSchema,
  ResourceTypeSchema,
  OriginResourceTypeSchema
} from '../../platform/utils/validation'

// Note: ExecutionTargetSchema and OriginTrackingSchema are now imported from api-schemas.ts
// This ensures consistent validation across all execution endpoints

// Re-export for backward compatibility
export { ExecutionTargetSchema, OriginTrackingSchema }

// ============================================================================
// SCHEDULE ITEM SCHEMAS
// Note: These are canonical domain schemas. API-level schemas with additional
// validation constraints are in api-schemas.ts
// ============================================================================

/**
 * Relative schedule item validation
 * Used for schedule items with offsets from an anchor date
 *
 * Offset format: [+/-][number][unit]
 * - Units: d (days), h (hours), m (minutes)
 * - Examples: '-7d', '+3d', '-2h', '+30m'
 *
 * @example
 * ```typescript
 * {
 *   offset: '-7d',  // 7 days before anchor
 *   payload: { reminder: 'one week before' },
 *   label: 'Week before reminder'
 * }
 * ```
 */
export const RelativeScheduleItemSchema = z.object({
  offset: z.string().regex(/^[+-]\d+[dhm]$/, 'Invalid offset format. Use +3d, -2h, +30m, etc.'),
  payload: z.record(z.string(), z.unknown()),
  label: z.string().optional()
})

/**
 * Absolute schedule item validation
 * Used for schedule items with fixed datetime
 *
 * @example
 * ```typescript
 * {
 *   runAt: '2025-03-15T09:00:00Z',
 *   payload: { event: 'launch' },
 *   label: 'Product launch notification'
 * }
 * ```
 */
export const AbsoluteScheduleItemSchema = z.object({
  runAt: z.string().datetime({ message: 'Invalid datetime format' }),
  payload: z.record(z.string(), z.unknown()),
  label: z.string().optional()
})

// ============================================================================
// SCHEDULE CONFIG SCHEMAS (DISCRIMINATED UNION)
// ============================================================================

/**
 * Recurring schedule configuration
 * Supports cron expressions or predefined intervals with timezone
 *
 * Security:
 * - timezone validated as string (IANA timezone validation at service layer)
 * - endAt prevents infinite schedules
 *
 * @example
 * ```typescript
 * // Cron-based (every Monday at 9am)
 * {
 *   type: 'recurring',
 *   cron: '0 9 * * 1',
 *   timezone: 'America/New_York',
 *   payload: { report: 'weekly' }
 * }
 *
 * // Interval-based (daily at 10:30)
 * {
 *   type: 'recurring',
 *   interval: 'daily',
 *   time: '10:30',
 *   timezone: 'Europe/London',
 *   payload: { check: 'daily' }
 * }
 * ```
 */
export const RecurringScheduleConfigSchema = z
  .object({
    type: z.literal('recurring'),
    cron: z.string().optional(),
    interval: z.enum(['daily', 'weekly', 'monthly']).optional(),
    time: z
      .string()
      .regex(/^\d{2}:\d{2}$/, 'Time must be in HH:MM format')
      .optional(),
    timezone: z.string().min(1, 'Timezone is required'),
    payload: z.record(z.string(), z.unknown()),
    endAt: z.string().datetime().nullable().optional(),
    overduePolicy: z.enum(['skip', 'execute']).optional()
  })
  .refine((data) => data.cron || data.interval, { message: 'Either cron or interval must be provided' })

/**
 * Relative schedule configuration
 * Schedule items relative to an anchor date (e.g., event countdown)
 *
 * @example
 * ```typescript
 * {
 *   type: 'relative',
 *   anchorAt: '2025-06-01T00:00:00Z',
 *   anchorLabel: 'Product Launch',
 *   items: [
 *     { offset: '-30d', payload: { reminder: '30 days out' } },
 *     { offset: '-7d', payload: { reminder: '1 week out' } },
 *     { offset: '-1d', payload: { reminder: 'tomorrow' } }
 *   ]
 * }
 * ```
 */
export const RelativeScheduleConfigSchema = z.object({
  type: z.literal('relative'),
  anchorAt: z.string().datetime({ message: 'Invalid anchor datetime' }),
  anchorLabel: z.string().optional(),
  items: z.array(RelativeScheduleItemSchema).min(1, 'At least one item required'),
  overduePolicy: z.enum(['skip', 'execute']).optional()
})

/**
 * Absolute schedule configuration
 * Schedule items at specific fixed datetimes
 *
 * @example
 * ```typescript
 * {
 *   type: 'absolute',
 *   items: [
 *     { runAt: '2025-01-15T10:00:00Z', payload: { event: 'first' } },
 *     { runAt: '2025-02-15T10:00:00Z', payload: { event: 'second' } }
 *   ]
 * }
 * ```
 */
export const AbsoluteScheduleConfigSchema = z.object({
  type: z.literal('absolute'),
  items: z.array(AbsoluteScheduleItemSchema).min(1, 'At least one item required'),
  overduePolicy: z.enum(['skip', 'execute']).optional()
})

/**
 * Task schedule configuration discriminated union
 * Efficiently validates one of three schedule types based on 'type' field
 *
 * Uses Zod's discriminatedUnion for optimal parsing performance
 */
export const TaskScheduleConfigSchema = z.discriminatedUnion('type', [
  RecurringScheduleConfigSchema,
  RelativeScheduleConfigSchema,
  AbsoluteScheduleConfigSchema
])

// ============================================================================
// CREATE SCHEDULE INPUT SCHEMA
// ============================================================================

/**
 * Target schema for schedule creation
 * Simplified version without payload (payload is in schedule config)
 */
const ScheduleTargetSchema = z.object({
  resourceType: ResourceTypeSchema,
  resourceId: NonEmptyStringSchema.max(255)
})

/**
 * Optional origin tracking for schedule creation
 * All fields are optional for schedules created via API
 */
const OptionalOriginTrackingSchema = z.object({
  originExecutionId: UuidSchema.optional(),
  originResourceType: OriginResourceTypeSchema.optional(),
  originResourceId: z.string().max(100).optional()
})

/**
 * Create schedule input validation
 * Complete input schema for creating a new task schedule
 *
 * Security Features:
 * - organizationId validated as UUID (multi-tenancy)
 * - name length limited (prevents DoS)
 * - target validated with resource type enum
 * - schedule config validated with discriminated union
 * - maxRetries bounded (0-10)
 *
 * @example
 * ```typescript
 * {
 *   organizationId: '550e8400-e29b-41d4-a716-446655440000',
 *   name: 'Weekly Report Schedule',
 *   description: 'Sends weekly analytics report',
 *   target: {
 *     resourceType: 'workflow',
 *     resourceId: 'weekly-report-workflow'
 *   },
 *   scheduleConfig: {
 *     type: 'recurring',
 *     interval: 'weekly',
 *     time: '09:00',
 *     timezone: 'America/New_York',
 *     payload: { reportType: 'analytics' }
 *   },
 *   maxRetries: 3
 * }
 * ```
 */
export const CreateScheduleInputSchema = z
  .object({
    organizationId: UuidSchema,
    name: NonEmptyStringSchema.max(255),
    description: z.string().max(1000).optional(),

    target: ScheduleTargetSchema,
    scheduleConfig: TaskScheduleConfigSchema,

    maxRetries: z.number().int().min(0).max(10).optional().default(3),
    idempotencyKey: z.string().max(255).optional(),
    metadata: z.record(z.string(), z.unknown()).optional()
  })
  .merge(OptionalOriginTrackingSchema)

// ============================================================================
// INFERRED TYPES
// ============================================================================

/** Validated relative schedule item input */
export type RelativeScheduleItemInput = z.infer<typeof RelativeScheduleItemSchema>

/** Validated absolute schedule item input */
export type AbsoluteScheduleItemInput = z.infer<typeof AbsoluteScheduleItemSchema>

/** Validated recurring schedule config input */
export type RecurringScheduleConfigInput = z.infer<typeof RecurringScheduleConfigSchema>

/** Validated relative schedule config input */
export type RelativeScheduleConfigInput = z.infer<typeof RelativeScheduleConfigSchema>

/** Validated absolute schedule config input */
export type AbsoluteScheduleConfigInput = z.infer<typeof AbsoluteScheduleConfigSchema>

/** Validated task schedule config (union of all config types) */
export type TaskScheduleConfigInput = z.infer<typeof TaskScheduleConfigSchema>

/** Validated create schedule input */
export type CreateScheduleInputValidated = z.infer<typeof CreateScheduleInputSchema>
