import { z } from 'zod';

// ═══════════════════════════════════════════════════════════
// Enums & Constants
// ═══════════════════════════════════════════════════════════

export const PipelineStatus = ['active', 'paused', 'completed', 'failed', 'archived'] as const;
export const Priority = ['critical', 'high', 'medium', 'low'] as const;
export const TaskStatus = ['pending', 'claimed', 'in_progress', 'completed', 'expired', 'escalated'] as const;
export const TaskType = ['approval', 'review', 'decision', 'manual_action', 'fix_required'] as const;
export const ApprovalStatus = ['pending', 'approved', 'rejected', 'escalated'] as const;
export const ApprovalType = ['stage_gate', 'deploy', 'code_review', 'manual_check'] as const;
export const AgentStatus = ['idle', 'active', 'error', 'offline'] as const;
export const AgentType = ['ai_builder', 'test_runner', 'deployer', 'monitor'] as const;
export const AssetType = ['code', 'config', 'docs', 'build', 'test_report', 'screenshot'] as const;
export const StageStatus = ['pending', 'active', 'completed', 'skipped', 'failed'] as const;
export const Decision = ['approved', 'rejected', 'deferred', 'escalated'] as const;
export const NotificationType = [
  'task_assigned', 'approval_pending', 'sla_warning', 'sla_breach',
  'deploy_status', 'pipeline_completed', 'agent_error', 'feedback_processed',
] as const;
export const NotificationChannel = ['dashboard', 'discord', 'email', 'sms', 'push'] as const;

export const PIPELINE_STAGES_ORDERED = [
  'intake',
  'scaffolding',
  'building',
  'testing',
  'review',
  'staging',
  'production',
  'published',
] as const;

export type PipelineStage = (typeof PIPELINE_STAGES_ORDERED)[number];

// WebSocket event types (used by webhooks)
export const WS_EVENT_TYPES = [
  'pipeline.created', 'pipeline.updated', 'pipeline.stage_changed',
  'pipeline.completed', 'pipeline.failed', 'pipeline.blocked',
  'task.created', 'task.claimed', 'task.completed',
  'task.sla_warning', 'task.sla_breached', 'task.escalated',
  'approval.pending', 'approval.approved', 'approval.rejected',
  'agent.status_changed', 'agent.heartbeat',
  'asset.created', 'asset.updated',
  'deploy.started', 'deploy.succeeded', 'deploy.failed',
  'feedback.received', 'feedback.processed',
] as const;

export type WebSocketEventType = (typeof WS_EVENT_TYPES)[number];

// ═══════════════════════════════════════════════════════════
// Zod Schemas — Input Validation
// ═══════════════════════════════════════════════════════════

// ─── Pipelines ─────────────────────────────────────────────

export const CreatePipelineSchema = z.object({
  name: z.string().min(1).max(255),
  template: z.string().max(100).default('mcp-server-standard'),
  platform: z.string().max(100).optional(),
  priority: z.enum(Priority).default('medium'),
  config: z.record(z.unknown()).optional(),
  assigneeId: z.string().uuid().optional(),
});

export const UpdatePipelineSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  priority: z.enum(Priority).optional(),
  status: z.enum(PipelineStatus).optional(),
  config: z.record(z.unknown()).optional(),
  assigneeId: z.string().uuid().nullable().optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const AdvanceStageSchema = z.object({
  targetStage: z.enum(PIPELINE_STAGES_ORDERED).optional(),
  skipValidation: z.boolean().default(false),
  notes: z.string().optional(),
});

export const PipelineQuerySchema = z.object({
  status: z.enum(PipelineStatus).optional(),
  stage: z.string().optional(),
  priority: z.enum(Priority).optional(),
  assigneeId: z.string().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().min(1).default(1),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

// ─── Tasks ────────────────────────────────────────────────

export const TaskQuerySchema = z.object({
  status: z.enum(TaskStatus).optional(),
  priority: z.enum(Priority).optional(),
  type: z.enum(TaskType).optional(),
  pipelineId: z.string().uuid().optional(),
  assigneeId: z.string().optional(), // supports "me"
  slaBreached: z.coerce.boolean().optional(),
  sort: z.string().optional(),
  page: z.coerce.number().int().min(1).default(1),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

export const BulkTaskSchema = z.object({
  action: z.enum(['approve', 'reject', 'defer']),
  taskIds: z.array(z.string().uuid()).min(1).max(50),
  notes: z.string().optional(),
});

export const CompleteTaskSchema = z.object({
  decision: z.enum(Decision),
  notes: z.string().optional(),
  decisionData: z.record(z.unknown()).optional(),
});

export const ReassignTaskSchema = z.object({
  assigneeId: z.string().uuid(),
  reason: z.string().optional(),
});

// ─── Approvals ────────────────────────────────────────────

export const ApproveSchema = z.object({
  notes: z.string().optional(),
  conditions: z.array(z.string()).optional(),
});

export const RejectSchema = z.object({
  reason: z.string().min(1),
  requestedChanges: z.array(z.string()).optional(),
  severity: z.enum(['minor', 'major', 'critical']).default('major'),
});

// ─── Agents ───────────────────────────────────────────────

export const AgentHeartbeatSchema = z.object({
  status: z.enum(AgentStatus),
  metrics: z.record(z.number()).optional(),
  currentTaskId: z.string().uuid().nullable().optional(),
  currentPipelineId: z.string().uuid().nullable().optional(),
});

export const AgentActivityQuerySchema = z.object({
  since: z.string().datetime().optional(),
  limit: z.coerce.number().int().min(1).max(200).default(50),
});

// ─── Assets ───────────────────────────────────────────────

export const AssetQuerySchema = z.object({
  type: z.enum(AssetType).optional(),
  stage: z.string().optional(),
  page: z.coerce.number().int().min(1).default(1),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

export const CreateAssetSchema = z.object({
  pipelineId: z.string().uuid(),
  stage: z.string().optional(),
  type: z.enum(AssetType),
  name: z.string().min(1).max(500),
  path: z.string().max(1000).optional(),
  contentType: z.string().max(255).optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const AssetDiffQuerySchema = z.object({
  fromVersion: z.coerce.number().int().min(1),
  toVersion: z.coerce.number().int().min(1).optional(),
});

// ─── Notifications ────────────────────────────────────────

export const NotificationQuerySchema = z.object({
  unread: z.coerce.boolean().optional(),
  type: z.enum(NotificationType).optional(),
  page: z.coerce.number().int().min(1).default(1),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

// ─── Audit ────────────────────────────────────────────────

export const AuditQuerySchema = z.object({
  entityType: z.string().optional(),
  entityId: z.string().uuid().optional(),
  action: z.string().optional(),
  actorId: z.string().uuid().optional(),
  since: z.string().datetime().optional(),
  until: z.string().datetime().optional(),
  page: z.coerce.number().int().min(1).default(1),
  limit: z.coerce.number().int().min(1).max(100).default(50),
});

// ─── Webhooks ─────────────────────────────────────────────

export const CreateWebhookSchema = z.object({
  url: z.string().url(),
  events: z.array(z.string()).min(1),
  secret: z.string().min(16).optional(),
});

// ═══════════════════════════════════════════════════════════
// Response Types
// ═══════════════════════════════════════════════════════════

export type ApiResponse<T> = {
  success: true;
  data: T;
  meta?: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
  };
};

export type ApiError = {
  success: false;
  error: {
    code: string;
    message: string;
    details?: unknown;
  };
};

// ═══════════════════════════════════════════════════════════
// JWT / Auth Types
// ═══════════════════════════════════════════════════════════

export type UserRole = 'owner' | 'admin' | 'operator' | 'viewer' | 'agent';

export type JWTPayload = {
  sub: string;       // user ID
  role: UserRole;
  scopes: string[];
  iat: number;
  exp: number;
};

export type AuthContext = {
  userId: string;
  role: UserRole;
  scopes: string[];
};

// ═══════════════════════════════════════════════════════════
// Task Stats
// ═══════════════════════════════════════════════════════════

export interface TaskStats {
  pending: number;
  inProgress: number;
  blocked: number;
  avgWaitTimeMinutes: number;
  slaBreaches: number;
  byPriority: Record<string, number>;
  byType: Record<string, number>;
}
