/**
 * API Types
 *
 * Shared request/response types for API endpoints.
 */

import { z } from 'zod';

// ============================================================
// Health
// ============================================================

export interface HealthResponse {
  status: 'healthy' | 'starting' | 'unhealthy';
  version: string;
  uptimeSeconds: number;
  repoRoot?: string;
  database: {
    connected: boolean;
    nodeCount?: number;
    relationshipCount?: number;
    error?: string;
  };
  timestamp: string;
}

// ============================================================
// Database
// ============================================================

export interface DbStats {
  nodeCount: number;
  relationshipCount: number;
  fileCount: number;
  functionCount: number;
  classCount: number;
  moduleCount: number;
}

export interface DbInitResponse {
  success: boolean;
  message: string;
  stats?: DbStats;
}

// ============================================================
// Indexing
// ============================================================

export const IndexRequestSchema = z.object({
  repoPath: z.string(),
  options: z.object({
    changedOnly: z.boolean().default(false),
    maxWorkers: z.number().int().positive().default(4),
  }).optional(),
});

export type IndexRequest = z.infer<typeof IndexRequestSchema>;

export interface IndexStatus {
  isIndexed: boolean;
  lastIndexedCommit?: string;
  fileCount: number;
  functionCount: number;
  classCount: number;
  moduleCount: number;
}

export interface IndexProgress {
  phase: 'scanning' | 'parsing' | 'building' | 'complete';
  filesProcessed: number;
  totalFiles: number;
  currentFile?: string;
  percent: number;
}

// ============================================================
// Search
// ============================================================

export const SearchRequestSchema = z.object({
  query: z.string().min(1),
  type: z.enum(['semantic', 'text']).default('semantic'),
  limit: z.number().int().positive().default(20),
  entityTypes: z.array(z.enum(['File', 'Function', 'Class'])).optional(),
  minScore: z.number().min(0).max(1).optional(),
});

export type SearchRequest = z.infer<typeof SearchRequestSchema>;

export interface SearchResult {
  qualifiedName: string;
  name: string;
  entityType: 'File' | 'Function' | 'Class';
  filePath?: string;
  lineNumber?: number;
  score: number;
  description?: string;
}

export interface SearchResponse {
  results: SearchResult[];
  total: number;
  query: string;
  searchType: 'semantic' | 'text';
}

// ============================================================
// Graph Query
// ============================================================

export interface EntityResult {
  qualifiedName: string;
  name: string;
  entityType: 'File' | 'Function' | 'Class' | 'Module';
  filePath?: string;
  lineStart?: number;
  lineEnd?: number;
  description?: string;
}

export const ExpandRequestSchema = z.object({
  entityType: z.enum(['File', 'Class', 'Function']),
  qualifiedName: z.string(),
  maxHops: z.number().int().positive().default(2),
});

export type ExpandRequest = z.infer<typeof ExpandRequestSchema>;

export interface ExpandResponse {
  entity: EntityResult;
  callers: EntityResult[];
  callees: EntityResult[];
  dependencies: EntityResult[];
  dependents: EntityResult[];
}

export interface CallersResponse {
  qualifiedName: string;
  callers: EntityResult[];
  depth: number;
}

export interface CalleesResponse {
  qualifiedName: string;
  callees: EntityResult[];
  depth: number;
}

export interface HierarchyResponse {
  qualifiedName: string;
  parents: EntityResult[];
  children: EntityResult[];
}

// ============================================================
// Context
// ============================================================

export const ContextUpdateRequestSchema = z.object({
  explorationSteps: z.array(z.object({
    toolName: z.string(),
    entitiesDiscovered: z.array(z.string()),
  })).optional(),
  modifiedFiles: z.array(z.string()).optional(),
});

export type ContextUpdateRequest = z.infer<typeof ContextUpdateRequestSchema>;

export const ContextQuerySchema = z.object({
  query: z.string().optional(),
  minScore: z.number().min(0).max(1).optional(),
  maxItems: z.number().int().positive().optional(),
  rerank: z.boolean().optional(),
});

export type ContextQuery = z.infer<typeof ContextQuerySchema>;

// ============================================================
// Verify
// ============================================================

export const VerifyRequestSchema = z.object({
  goal: z.string().optional(),
  filesChanged: z.array(z.string()).optional(),
  gitDiff: z.string().optional(),
  verifierNames: z.array(z.string()).optional(),
});

export type VerifyRequest = z.infer<typeof VerifyRequestSchema>;

// ============================================================
// Embed
// ============================================================

export interface EmbedStatus {
  totalEntities: number;
  embeddedEntities: number;
  coverage: number;
  model: string;
}

export const EmbedRequestSchema = z.object({
  entityTypes: z.array(z.enum(['Function', 'Class'])).default(['Function', 'Class']),
  reindex: z.boolean().default(false),
  batchSize: z.number().int().positive().default(100),
});

export type EmbedRequest = z.infer<typeof EmbedRequestSchema>;

// ============================================================
// Generic
// ============================================================

export interface ApiError {
  error: string;
  message: string;
  statusCode: number;
}

export interface SuccessResponse {
  success: boolean;
  message?: string;
}
