/**
 * Core TypeScript interfaces for polling system
 */

// import { z } from 'zod';

// Core polling interfaces
export interface GenericPollingRequest<TRequest, TResponse> {
  // Request configuration
  endpoint: string;
  method: 'GET' | 'POST' | 'PUT' | 'DELETE';
  headers?: Record<string, string>;
  body?: TRequest;
  
  // Idempotency (required for POST requests)
  idempotencyKey?: string; // Auto-generated if not provided
  
  // Response handling
  responseSchema: ResponseSchema<TResponse>;
  transformResponse?: (rawResponse: unknown) => TResponse;
  
  // Error handling
  retryConfig?: RetryConfiguration;
  timeoutMs?: number;
  
  // Authentication
  authConfig?: AuthenticationConfig;
}

export interface ResponseSchema<T> {
  // Schema validation
  validate: (data: unknown) => data is T;
  // Error transformation
  transformError?: (error: unknown) => PollingError;
}

export interface PollingResult<T> {
  success: boolean;
  data?: T;
  error?: PollingError;
  metadata: {
    requestId: string;
    timestamp: string;
    duration: number;
    retryCount: number;
  };
}

export interface PollingError {
  code: string;
  message: string;
  details?: Record<string, unknown>;
  retryable: boolean;
  retryAfter?: number;
}

// Backoff policy
export interface BackoffPolicy {
  // Base configuration
  maxAttempts: number;
  baseDelayMs: number;
  maxDelayMs: number;
  
  // Strategy selection
  strategy: 'exponential' | 'linear' | 'fixed';
  
  // Jitter configuration
  jitterEnabled: boolean;
  jitterFactor: number; // 0.0 to 1.0 (e.g., 0.25 = ±25% jitter)
  
  // Retry-After integration
  respectRetryAfter: boolean;
  retryAfterMaxMs?: number; // Cap Retry-After values
}

export interface RetryConfiguration {
  maxAttempts: number;
  backoffStrategy: 'exponential' | 'linear' | 'fixed';
  baseDelayMs: number;
}

// Authentication
export interface AuthenticationConfig {
  type: 'jwt' | 'bearer' | 'api_key';
  token?: string;
  refreshToken?: string;
  expiresAt?: number;
}

// Scheduling
export interface PollingScheduleConfig<TRequest, TResponse> {
  request: GenericPollingRequest<TRequest, TResponse>;
  schedule: {
    cronExpression: string;
    timezone: string;
    maxConcurrentPolls: number;
  };
  notificationConfig?: NotificationConfig;
  stateConfig: {
    watermarkKey: string;
    storageAdapter: StorageAdapter;
  };
}

export interface NotificationConfig {
  enabled: boolean;
  templates: NotificationTemplates;
  groupingRules: NotificationGroupingRules;
}

export interface NotificationTemplates {
  singleUpdate: string;
  multipleUpdates: string;
}

export interface NotificationGroupingRules {
  maxGroupSize: number;
  timeWindowMinutes: number;
}

// Storage
export interface StorageAdapter {
  get(key: string): Promise<unknown>;
  set(key: string, value: unknown): Promise<void>;
  delete(key: string): Promise<void>;
  exists(key: string): Promise<boolean>;
}

// Context
export interface PollingContext {
  activeDid: string;
  apiServer: string;
  storageAdapter: StorageAdapter;
  authManager: AuthenticationManager;
}

export interface AuthenticationManager {
  getCurrentToken(): Promise<string | null>;
  refreshToken(): Promise<string>;
  validateToken(token: string): Promise<boolean>;
}

// Starred Projects specific types
export interface StarredProjectsRequest {
  planIds: string[];
  afterId?: string;
  beforeId?: string;
  limit?: number;
}

export interface StarredProjectsResponse {
  data: PlanSummaryAndPreviousClaim[];
  hitLimit: boolean;
  pagination: {
    hasMore: boolean;
    nextAfterId: string | null;
  };
}

export interface PlanSummaryAndPreviousClaim {
  planSummary: PlanSummary;
  previousClaim?: PreviousClaim;
}

export interface PlanSummary {
  jwtId: string;
  handleId: string;
  name: string;
  description: string;
  issuerDid: string;
  agentDid: string;
  startTime: string;
  endTime: string;
  locLat?: number;
  locLon?: number;
  url?: string;
  version: string;
}

export interface PreviousClaim {
  jwtId: string;
  claimType: string;
  claimData: Record<string, unknown>;
  metadata: {
    createdAt: string;
    updatedAt: string;
  };
}

// Telemetry
export interface TelemetryMetrics {
  // Low-cardinality metrics (Prometheus counters/gauges)
  'starred_projects_poll_attempts_total': number;
  'starred_projects_poll_success_total': number;
  'starred_projects_poll_failure_total': number;
  'starred_projects_poll_duration_seconds': number;
  'starred_projects_changes_found_total': number;
  'starred_projects_notifications_generated_total': number;
  'starred_projects_error_total': number;
  'starred_projects_rate_limit_total': number;
  'starred_projects_api_latency_seconds': number;
  'starred_projects_api_throughput_rps': number;
  'starred_projects_outbox_size': number;
  'starred_projects_outbox_backpressure_active': number;
}

export interface TelemetryLogs {
  // Request-level details (logs only)
  requestId: string;
  activeDid: string;
  projectCount: number;
  changeCount: number;
  duration: number;
  error?: string;
  metadata?: Record<string, unknown>;
}

// Clock sync
export interface ClockSyncConfig {
  serverTimeSource: 'ntp' | 'system' | 'atomic';
  ntpServers: string[];
  maxClockSkewSeconds: number;
  skewCheckIntervalMs: number;
  jwtClockSkewTolerance: number;
  jwtMaxAge: number;
}

// Storage pressure
export interface OutboxPressureConfig {
  maxUndelivered: number;
  cleanupIntervalMs: number;
  backpressureThreshold: number;
  evictionPolicy: 'fifo' | 'lifo' | 'priority';
}
