import { z } from 'zod';
import { FileErrorPayloadSchema } from './errors.js';
import { IdempotencyKeySchema, RequestIdSchema } from './primitives.js';

const KIND_REQUEST_PATTERN = /^shade\.fs\.[A-Za-z0-9.-]+\/v\d+$/;
const KIND_RESPONSE_PATTERN = /^shade\.fs\.[A-Za-z0-9.-]+\/v\d+\.response$/;

/**
 * Request envelope. Carries op kind, correlation id, args (validated per
 * op), idempotency key (mutations only), and an Ed25519 signature binding
 * `(sender, kind, id, argsHash, signedAt)`.
 */
export const RpcRequestSchema = z.object({
  kind: z.string().regex(KIND_REQUEST_PATTERN, 'invalid request kind'),
  id: RequestIdSchema,
  args: z.unknown(),
  idempotencyKey: IdempotencyKeySchema.optional(),
  attempt: z.number().int().positive().optional(),
  deadlineMs: z.number().int().positive().optional(),
  sig: z.string().min(1).max(128),
  signedAt: z.number().int().positive(),
});
export type RpcRequest = z.infer<typeof RpcRequestSchema>;

export const RpcResponseSchema = z.object({
  kind: z.string().regex(KIND_RESPONSE_PATTERN, 'invalid response kind'),
  id: RequestIdSchema,
  result: z.unknown(),
});
export type RpcResponse = z.infer<typeof RpcResponseSchema>;

export const RpcErrorSchema = z.object({
  kind: z.literal('shade.fs.error/v1'),
  id: RequestIdSchema,
  error: FileErrorPayloadSchema,
});
export type RpcError = z.infer<typeof RpcErrorSchema>;

export const RpcCancelSchema = z.object({
  kind: z.literal('shade.fs.cancel/v1'),
  id: RequestIdSchema,
  reason: z.string().max(512).optional(),
});
export type RpcCancel = z.infer<typeof RpcCancelSchema>;

export type RpcEnvelope = RpcRequest | RpcResponse | RpcError | RpcCancel;
