/**
 * Zod schemas for strong structural validation
 */

import { z } from 'zod';
import { JWT_ID_PATTERN } from './constants';

// Core schemas
export const PlanSummarySchema = z.object({
  jwtId: z.string().regex(JWT_ID_PATTERN, 'Invalid JWT ID format'),
  handleId: z.string().min(1),
  name: z.string().min(1),
  description: z.string(),
  issuerDid: z.string().startsWith('did:key:'),
  agentDid: z.string().startsWith('did:key:'),
  startTime: z.string().datetime(),
  endTime: z.string().datetime(),
  locLat: z.number().nullable().optional(),
  locLon: z.number().nullable().optional(),
  url: z.string().url().nullable().optional(),
  version: z.string()
});

export const PreviousClaimSchema = z.object({
  jwtId: z.string().regex(JWT_ID_PATTERN),
  claimType: z.string(),
  claimData: z.record(z.unknown()),
  metadata: z.object({
    createdAt: z.string().datetime(),
    updatedAt: z.string().datetime()
  })
});

export const PlanSummaryAndPreviousClaimSchema = z.object({
  planSummary: PlanSummarySchema,
  previousClaim: PreviousClaimSchema.optional()
});

export const StarredProjectsResponseSchema = z.object({
  data: z.array(PlanSummaryAndPreviousClaimSchema),
  hitLimit: z.boolean(),
  pagination: z.object({
    hasMore: z.boolean(),
    nextAfterId: z.string().regex(JWT_ID_PATTERN).nullable()
  })
});

export const StarredProjectsRequestSchema = z.object({
  planIds: z.array(z.string()).min(1),
  afterId: z.string().regex(JWT_ID_PATTERN).optional(),
  beforeId: z.string().regex(JWT_ID_PATTERN).optional(),
  limit: z.number().min(1).max(100).default(100)
});

// Deep link parameter validation
export const DeepLinkParamsSchema = z.object({
  jwtIds: z.array(z.string().regex(JWT_ID_PATTERN)).max(10).optional(),
  projectId: z.string().regex(/^[a-zA-Z0-9_-]+$/).optional(),
  jwtId: z.string().regex(JWT_ID_PATTERN).optional(),
  shortlink: z.string().min(1).optional()
}).refine(
  (data) => data.jwtIds || data.jwtId || data.projectId || data.shortlink,
  'At least one of jwtIds, jwtId, projectId, or shortlink must be provided'
);

// Error response schema
export const ErrorResponseSchema = z.object({
  error: z.string(),
  code: z.string().optional(),
  message: z.string(),
  details: z.record(z.unknown()).optional(),
  retryAfter: z.number().optional(),
  requestId: z.string().optional()
});

// Rate limit response schema
export const RateLimitResponseSchema = z.object({
  error: z.literal('Rate limit exceeded'),
  code: z.literal('RATE_LIMIT_EXCEEDED'),
  message: z.string(),
  details: z.object({
    limit: z.number(),
    window: z.string(),
    resetAt: z.string().datetime(),
    remaining: z.number().optional()
  }),
  retryAfter: z.number(),
  requestId: z.string()
});

// Acknowledgment request schema
export const AcknowledgmentRequestSchema = z.object({
  acknowledgedJwtIds: z.array(z.string().regex(JWT_ID_PATTERN)).min(1),
  acknowledgedAt: z.string().datetime(),
  clientVersion: z.string()
});

// Acknowledgment response schema
export const AcknowledgmentResponseSchema = z.object({
  acknowledged: z.number(),
  failed: z.number(),
  alreadyAcknowledged: z.number(),
  acknowledgmentId: z.string(),
  timestamp: z.string().datetime()
});

// Clock sync response schema
export const ClockSyncResponseSchema = z.object({
  serverTime: z.number(),
  clientTime: z.number(),
  offset: z.number(),
  ntpServers: z.array(z.string()).optional()
});

// Type exports for use in host apps (only export types not already in types.ts)
export type DeepLinkParams = z.infer<typeof DeepLinkParamsSchema>;
export type ErrorResponse = z.infer<typeof ErrorResponseSchema>;
export type RateLimitResponse = z.infer<typeof RateLimitResponseSchema>;
export type AcknowledgmentRequest = z.infer<typeof AcknowledgmentRequestSchema>;
export type AcknowledgmentResponse = z.infer<typeof AcknowledgmentResponseSchema>;
export type ClockSyncResponse = z.infer<typeof ClockSyncResponseSchema>;
