/**
 * CDN Pipeline module — types and schemas.
 * Manages asset uploads, purge requests, and CDN origin configuration.
 * Assets are stored in Azure Blob and served via CDN with cache-busting.
 */

import { z } from 'zod';

// ── Asset Types ──────────────────────────────────────────────────

export type AssetCategory = 'image' | 'font' | 'script' | 'style' | 'document' | 'video' | 'other';

export interface CdnAssetDoc {
  id: string;
  productId: string;
  /** Original filename uploaded by the user */
  originalName: string;
  /** Blob storage path (container/path/hash.ext) */
  blobPath: string;
  /** Public CDN URL */
  cdnUrl: string;
  /** Content hash for cache-busting (SHA-256 first 16 hex chars) */
  contentHash: string;
  /** MIME type */
  mimeType: string;
  /** File size in bytes */
  sizeBytes: number;
  category: AssetCategory;
  /** Optional metadata (alt text, dimensions, etc.) */
  metadata?: Record<string, unknown>;
  /** Upload user */
  uploadedBy: string;
  /** Whether asset is publicly accessible */
  isPublic: boolean;
  createdAt: string;
  updatedAt: string;
}

export interface CdnPurgeRequestDoc {
  id: string;
  productId: string;
  /** Glob patterns to purge (e.g. /assets/img/*) */
  patterns: string[];
  /** Status of the purge */
  status: 'pending' | 'processing' | 'completed' | 'failed';
  /** Number of URLs purged */
  purgedCount: number;
  requestedBy: string;
  completedAt: string | null;
  error: string | null;
  createdAt: string;
}

export interface CdnOriginConfigDoc {
  id: string;
  productId: string;
  /** Custom domain (e.g. cdn.myapp.com) */
  customDomain: string | null;
  /** Default cache TTL in seconds */
  defaultCacheTtlSeconds: number;
  /** Per-category cache overrides */
  categoryTtlOverrides: Partial<Record<AssetCategory, number>>;
  /** Allowed CORS origins */
  corsOrigins: string[];
  /** Whether to enable Brotli compression */
  brotliEnabled: boolean;
  /** Whether to enable WebP auto-conversion for images */
  webpAutoConvert: boolean;
  updatedAt: string;
  updatedBy: string;
}

// ── Schemas ──────────────────────────────────────────────────────

export const UploadAssetSchema = z.object({
  originalName: z.string().min(1).max(255),
  mimeType: z.string().min(1).max(128),
  sizeBytes: z
    .number()
    .int()
    .min(1)
    .max(100 * 1024 * 1024), // 100 MB max
  category: z
    .enum(['image', 'font', 'script', 'style', 'document', 'video', 'other'])
    .default('other'),
  contentHash: z.string().min(8).max(64),
  blobPath: z.string().min(1).max(512),
  metadata: z.record(z.unknown()).optional(),
  isPublic: z.boolean().default(true),
});

export const PurgeRequestSchema = z.object({
  patterns: z.array(z.string().min(1).max(256)).min(1).max(50),
});

export const UpdateOriginConfigSchema = z.object({
  customDomain: z.string().max(253).nullable().optional(),
  defaultCacheTtlSeconds: z.number().int().min(0).max(31536000).optional(), // up to 1 year
  categoryTtlOverrides: z
    .record(
      z.enum(['image', 'font', 'script', 'style', 'document', 'video', 'other']),
      z.number().int().min(0)
    )
    .optional(),
  corsOrigins: z
    .array(z.string().url().or(z.literal('*')))
    .max(20)
    .optional(),
  brotliEnabled: z.boolean().optional(),
  webpAutoConvert: z.boolean().optional(),
});

export type UploadAssetInput = z.infer<typeof UploadAssetSchema>;
export type PurgeRequestInput = z.infer<typeof PurgeRequestSchema>;
export type UpdateOriginConfigInput = z.infer<typeof UpdateOriginConfigSchema>;
