import { z } from 'zod';

export const ServerStatus = z.enum([
  'draft',
  'queued',
  'generating',
  'building',
  'deploying',
  'live',
  'failed',
  'paused',
]);
export type ServerStatus = z.infer<typeof ServerStatus>;

export const BuildStatus = z.enum([
  'queued',
  'generating',
  'building',
  'deploying',
  'success',
  'failed',
  'cancelled',
]);
export type BuildStatus = z.infer<typeof BuildStatus>;

export const Plan = z.enum(['hobby', 'pro', 'team', 'enterprise']);
export type Plan = z.infer<typeof Plan>;

// ---- Generator output spec (what Claude returns) ----

export const ToolParam = z
  .object({
    type: z.enum(['string', 'number', 'boolean', 'array', 'object']),
    description: z.string().optional(),
    required: z.boolean().optional(),
    enum: z.array(z.string()).optional(),
  })
  .passthrough();

export const ToolSpec = z.object({
  name: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z][a-z0-9_]*$/, 'snake_case identifier required'),
  description: z.string().min(1).max(2000),
  inputSchema: z.record(z.string(), ToolParam),
  implementation: z.string().min(1).max(20_000),
});
export type ToolSpec = z.infer<typeof ToolSpec>;

export const ResourceSpec = z.object({
  uri: z.string().min(1),
  name: z.string().min(1),
  description: z.string().optional(),
  mimeType: z.string().optional(),
  implementation: z.string().min(1),
});
export type ResourceSpec = z.infer<typeof ResourceSpec>;

export const PromptSpec = z.object({
  name: z.string().min(1),
  description: z.string().optional(),
  arguments: z
    .array(z.object({ name: z.string(), description: z.string().optional(), required: z.boolean().optional() }))
    .optional(),
  template: z.string().min(1),
});
export type PromptSpec = z.infer<typeof PromptSpec>;

export const GeneratorSpec = z.object({
  name: z.string().min(1).max(128),
  description: z.string().max(2000).optional(),
  tools: z.array(ToolSpec).min(1).max(50),
  resources: z.array(ResourceSpec).max(50).default([]),
  prompts: z.array(PromptSpec).max(50).default([]),
  requiredSecrets: z.array(z.string().regex(/^[A-Z][A-Z0-9_]*$/)).max(30).default([]),
  scopes: z.array(z.string()).max(50).default([]),
  dependencies: z.record(z.string(), z.string()).default({}),
});
export type GeneratorSpec = z.infer<typeof GeneratorSpec>;

// ---- Build stream events ----

export const BuildEvent = z.discriminatedUnion('type', [
  z.object({
    type: z.literal('status'),
    status: BuildStatus,
    at: z.string(),
  }),
  z.object({
    type: z.literal('log'),
    level: z.enum(['info', 'warn', 'error']),
    message: z.string(),
    at: z.string(),
  }),
  z.object({
    type: z.literal('done'),
    status: BuildStatus,
    serverId: z.string().uuid(),
    publicUrl: z.string().nullable(),
    at: z.string(),
  }),
  z.object({
    type: z.literal('error'),
    message: z.string(),
    at: z.string(),
  }),
]);
export type BuildEvent = z.infer<typeof BuildEvent>;

// ---- API request payloads ----

export const SpecEditTool = z.object({
  name: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z][a-z0-9_]*$/, 'snake_case identifier required'),
  description: z.string().min(1).max(2000),
  inputSchema: z.record(z.string(), ToolParam),
});
export type SpecEditTool = z.infer<typeof SpecEditTool>;

export const SpecEdit = z.object({
  tools: z.array(SpecEditTool).min(1).max(50),
  requiredSecrets: z.array(z.string().regex(/^[A-Z][A-Z0-9_]*$/)).max(30).default([]),
});
export type SpecEdit = z.infer<typeof SpecEdit>;

export const CreateServerInput = z.object({
  name: z.string().min(1).max(128),
  slug: z
    .string()
    .min(1)
    .max(64)
    .regex(/^[a-z][a-z0-9-]*$/, 'lowercase, hyphenated'),
  prompt: z.string().min(10).max(8000),
  secrets: z.record(z.string(), z.string()).default({}),
  previewId: z.string().min(1).max(64).optional(),
  specEdit: SpecEdit.optional(),
  templateId: z.string().uuid().optional(),
});
export type CreateServerInput = z.infer<typeof CreateServerInput>;

export const PreviewInput = z.object({
  prompt: z.string().min(10).max(8000),
});
export type PreviewInput = z.infer<typeof PreviewInput>;

export const PreviewResult = z.object({
  previewId: z.string(),
  source: z.enum(['claude', 'mock']),
  spec: z.object({
    name: z.string(),
    description: z.string().optional(),
    tools: z.array(
      z.object({
        name: z.string(),
        description: z.string(),
        inputSchema: z.record(z.string(), z.unknown()),
      }),
    ),
    requiredSecrets: z.array(z.string()),
    scopes: z.array(z.string()),
  }),
});
export type PreviewResult = z.infer<typeof PreviewResult>;

export const IterateServerInput = z.object({
  prompt: z.string().min(10).max(8000),
  secrets: z.record(z.string(), z.string()).default({}),
});
export type IterateServerInput = z.infer<typeof IterateServerInput>;

// ---- Install snippets ----

export const InstallTarget = z.enum(['claude-desktop', 'cursor', 'chatgpt']);
export type InstallTarget = z.infer<typeof InstallTarget>;
