import type {
  Image,
  GenerationWithRelations,
  FlowWithCounts,
  LiveScopeWithStats,
  PaginationMeta,
  AliasScope,
} from './models';

// ========================================
// COMMON RESPONSE TYPES
// ========================================

export interface ApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: {
    message: string;
    code?: string;
    details?: unknown;
  };
}

export interface PaginatedResponse<T> {
  success: boolean;
  data: T[];
  pagination: PaginationMeta;
}

// ========================================
// GENERATION RESPONSES
// ========================================

export interface GenerationResponse {
  id: string;
  projectId: string;
  flowId: string | null;
  prompt: string; // Prompt actually used for generation
  originalPrompt: string | null; // User's original input (always populated for new generations)
  autoEnhance: boolean; // Whether prompt enhancement was applied
  aspectRatio: string | null;
  status: string;
  errorMessage: string | null;
  retryCount: number;
  processingTimeMs: number | null;
  cost: number | null;
  outputImageId: string | null;
  outputImage?: ImageResponse | undefined;
  referencedImages?: Array<{ imageId: string; alias: string }> | undefined;
  referenceImages?: ImageResponse[] | undefined;
  apiKeyId: string | null;
  meta: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
}

export type CreateGenerationResponse = ApiResponse<GenerationResponse>;
export type GetGenerationResponse = ApiResponse<GenerationResponse>;
export type ListGenerationsResponse = PaginatedResponse<GenerationResponse>;
export type RetryGenerationResponse = ApiResponse<GenerationResponse>;
export type DeleteGenerationResponse = ApiResponse<{ id: string; deletedAt: string }>;

// ========================================
// IMAGE RESPONSES
// ========================================

export interface ImageResponse {
  id: string;
  projectId: string;
  flowId: string | null;
  storageKey: string;
  storageUrl: string;
  mimeType: string;
  fileSize: number;
  width: number | null;
  height: number | null;
  source: string;
  alias: string | null;
  focalPoint: { x: number; y: number } | null;
  fileHash: string | null;
  generationId: string | null;
  apiKeyId: string | null;
  meta: Record<string, unknown> | null;
  createdAt: string;
  updatedAt: string;
  deletedAt: string | null;
}

export interface AliasResolutionResponse {
  alias: string;
  imageId: string;
  scope: AliasScope;
  flowId?: string | undefined;
  image: ImageResponse;
}

export type UploadImageResponse = ApiResponse<ImageResponse>;
export type GetImageResponse = ApiResponse<ImageResponse>;
export type ListImagesResponse = PaginatedResponse<ImageResponse>;
export type ResolveAliasResponse = ApiResponse<AliasResolutionResponse>;
export type UpdateImageResponse = ApiResponse<ImageResponse>;
export type DeleteImageResponse = ApiResponse<{ id: string }>; // Hard delete, no deletedAt

// ========================================
// FLOW RESPONSES
// ========================================

export interface FlowResponse {
  id: string;
  projectId: string;
  aliases: Record<string, string>;
  generationCount: number;
  imageCount: number;
  meta: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
}

export interface FlowWithDetailsResponse extends FlowResponse {
  generations?: GenerationResponse[];
  images?: ImageResponse[];
  resolvedAliases?: Record<string, ImageResponse>;
}

export type CreateFlowResponse = ApiResponse<FlowResponse>;
export type GetFlowResponse = ApiResponse<FlowResponse>;
export type ListFlowsResponse = PaginatedResponse<FlowResponse>;
export type UpdateFlowAliasesResponse = ApiResponse<FlowResponse>;
export type DeleteFlowAliasResponse = ApiResponse<FlowResponse>;
export type DeleteFlowResponse = ApiResponse<{ id: string }>;
export type ListFlowGenerationsResponse = PaginatedResponse<GenerationResponse>;
export type ListFlowImagesResponse = PaginatedResponse<ImageResponse>;

// ========================================
// LIVE SCOPE RESPONSES
// ========================================

export interface LiveScopeResponse {
  id: string;
  projectId: string;
  slug: string;
  allowNewGenerations: boolean;
  newGenerationsLimit: number;
  currentGenerations: number;
  lastGeneratedAt: string | null;
  meta: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
}

export interface LiveScopeWithImagesResponse extends LiveScopeResponse {
  images?: ImageResponse[];
}

export type CreateLiveScopeResponse = ApiResponse<LiveScopeResponse>;
export type GetLiveScopeResponse = ApiResponse<LiveScopeResponse>;
export type ListLiveScopesResponse = PaginatedResponse<LiveScopeResponse>;
export type UpdateLiveScopeResponse = ApiResponse<LiveScopeResponse>;
export type DeleteLiveScopeResponse = ApiResponse<{ id: string }>;
export type RegenerateScopeResponse = ApiResponse<{ regenerated: number; images: ImageResponse[] }>;

// ========================================
// LIVE GENERATION RESPONSE
// ========================================
// Note: Live generation streams image bytes directly
// Response headers include:
// - Content-Type: image/jpeg
// - Cache-Control: public, max-age=31536000
// - X-Cache-Status: HIT | MISS

// ========================================
// ANALYTICS RESPONSES
// ========================================

export interface AnalyticsSummary {
  projectId: string;
  flowId?: string;
  timeRange: {
    startDate: string;
    endDate: string;
  };
  generations: {
    total: number;
    success: number;
    failed: number;
    pending: number;
    successRate: number;
  };
  images: {
    total: number;
    generated: number;
    uploaded: number;
  };
  performance: {
    avgProcessingTimeMs: number;
    totalCostCents: number;
  };
  cache: {
    hits: number;
    misses: number;
    hitRate: number;
  };
}

export interface AnalyticsTimelineData {
  timestamp: string;
  generationsTotal: number;
  generationsSuccess: number;
  generationsFailed: number;
  avgProcessingTimeMs: number;
  costCents: number;
}

export interface AnalyticsTimeline {
  projectId: string;
  flowId?: string;
  granularity: 'hour' | 'day' | 'week';
  timeRange: {
    startDate: string;
    endDate: string;
  };
  data: AnalyticsTimelineData[];
}

export type GetAnalyticsSummaryResponse = ApiResponse<AnalyticsSummary>;
export type GetAnalyticsTimelineResponse = ApiResponse<AnalyticsTimeline>;

// ========================================
// ERROR RESPONSES
// ========================================

export interface ErrorResponse {
  success: false;
  error: {
    message: string;
    code?: string;
    details?: unknown;
  };
}

// ========================================
// HELPER TYPE CONVERTERS
// ========================================

export const toGenerationResponse = (gen: GenerationWithRelations): GenerationResponse => ({
  id: gen.id,
  projectId: gen.projectId,
  flowId: gen.flowId ?? gen.pendingFlowId ?? null, // Return actual flowId or pendingFlowId for client
  prompt: gen.prompt, // Prompt actually used
  originalPrompt: gen.originalPrompt, // User's original (always populated)
  autoEnhance: gen.prompt !== gen.originalPrompt, // True if prompts differ (enhancement happened)
  aspectRatio: gen.aspectRatio,
  status: gen.status,
  errorMessage: gen.errorMessage,
  retryCount: gen.retryCount,
  processingTimeMs: gen.processingTimeMs,
  cost: gen.cost,
  outputImageId: gen.outputImageId,
  outputImage: gen.outputImage ? toImageResponse(gen.outputImage) : undefined,
  referencedImages: gen.referencedImages as Array<{ imageId: string; alias: string }> | undefined,
  referenceImages: gen.referenceImages?.map((img) => toImageResponse(img)),
  apiKeyId: gen.apiKeyId,
  meta: gen.meta as Record<string, unknown>,
  createdAt: gen.createdAt.toISOString(),
  updatedAt: gen.updatedAt.toISOString(),
});

export const toImageResponse = (img: Image): ImageResponse => ({
  id: img.id,
  projectId: img.projectId,
  flowId: img.flowId ?? img.pendingFlowId ?? null, // Return actual flowId or pendingFlowId for client
  storageKey: img.storageKey,
  storageUrl: img.storageUrl,
  mimeType: img.mimeType,
  fileSize: img.fileSize,
  width: img.width,
  height: img.height,
  source: img.source,
  alias: img.alias,
  focalPoint: img.focalPoint as { x: number; y: number } | null,
  fileHash: img.fileHash,
  generationId: img.generationId,
  apiKeyId: img.apiKeyId,
  meta: img.meta as Record<string, unknown>,
  createdAt: img.createdAt.toISOString(),
  updatedAt: img.updatedAt.toISOString(),
  deletedAt: img.deletedAt?.toISOString() ?? null,
});

export const toFlowResponse = (flow: FlowWithCounts): FlowResponse => ({
  id: flow.id,
  projectId: flow.projectId,
  aliases: flow.aliases as Record<string, string>,
  generationCount: flow.generationCount,
  imageCount: flow.imageCount,
  meta: flow.meta as Record<string, unknown>,
  createdAt: flow.createdAt.toISOString(),
  updatedAt: flow.updatedAt.toISOString(),
});

export const toLiveScopeResponse = (scope: LiveScopeWithStats): LiveScopeResponse => ({
  id: scope.id,
  projectId: scope.projectId,
  slug: scope.slug,
  allowNewGenerations: scope.allowNewGenerations,
  newGenerationsLimit: scope.newGenerationsLimit,
  currentGenerations: scope.currentGenerations,
  lastGeneratedAt: scope.lastGeneratedAt?.toISOString() ?? null,
  meta: scope.meta as Record<string, unknown>,
  createdAt: scope.createdAt.toISOString(),
  updatedAt: scope.updatedAt.toISOString(),
});
