/**
 * Product Manifest Specification
 *
 * Defines the JSON schema for product.json files that capture everything
 * about a ByteLyst product — identity, theme, features, containers, flags, ports.
 *
 * @module @bytelyst/config/product-manifest
 */

import { z } from 'zod';

/**
 * Platform identifiers
 */
export const PlatformSchema = z.enum(['web', 'ios', 'android', 'desktop', 'watch']);

/**
 * Theme color token
 */
export const ColorTokenSchema = z.string().regex(/^#[0-9A-Fa-f]{6}$/, {
  message: 'Color must be a hex value like #5AE68C',
});

/**
 * Theme specification
 */
export const ThemeSchema = z.object({
  primary: ColorTokenSchema,
  secondary: ColorTokenSchema,
  accent: ColorTokenSchema,
  background: ColorTokenSchema,
  surface: ColorTokenSchema,
  text: ColorTokenSchema,
  error: ColorTokenSchema,
  warning: ColorTokenSchema,
  success: ColorTokenSchema,
});

/**
 * Cosmos container definition
 */
export const ContainerDefSchema = z.object({
  name: z.string(),
  partitionKey: z.string(),
  ttlSeconds: z.number().optional(),
  uniqueKeys: z.array(z.string()).optional(),
});

/**
 * Feature flag default
 */
export const FeatureFlagSchema = z.object({
  key: z.string(),
  defaultValue: z.union([z.boolean(), z.string(), z.number()]),
  description: z.string().optional(),
});

/**
 * Port configuration
 */
export const PortConfigSchema = z.object({
  service: z.number().optional(),
  dashboard: z.number().optional(),
  web: z.number().optional(),
});

/**
 * Product manifest schema (Zod)
 *
 * Example product.json:
 * ```json
 * {
 *   "id": "lysnrai",
 *   "name": "LysnrAI",
 *   "displayName": "LysnrAI",
 *   "bundleId": "com.saravana.lysnrai",
 *   "domain": "lysnrai.app",
 *   "description": "Voice-to-text dictation platform",
 *   "platforms": ["web", "ios", "android", "desktop"],
 *   "theme": {
 *     "primary": "#5AE68C",
 *     "secondary": "#5A8CFF",
 *     "accent": "#2EE6D6",
 *     "background": "#06070A",
 *     "surface": "#121725",
 *     "text": "#EFF4FF",
 *     "error": "#FF6E6E",
 *     "warning": "#F59E0B",
 *     "success": "#34D399"
 *   },
 *   "features": {
 *     "voiceDictation": true,
 *     "realtimeTranscription": true,
 *     "keyboardExtension": true,
 *     "cloudSync": true
 *   },
 *   "cosmos": {
 *     "containers": [
 *       { "name": "transcripts", "partitionKey": "/userId" },
 *       { "name": "sessions", "partitionKey": "/userId" }
 *     ]
 *   },
 *   "flags": [
 *     { "key": "new-ui-enabled", "defaultValue": false },
 *     { "key": "max-audio-duration", "defaultValue": 300 }
 *   ],
 *   "ports": {
 *     "service": 4015,
 *     "dashboard": 3002
 *   }
 * }
 * ```
 */
export const ProductManifestSchema = z.object({
  // Identity (all required)
  id: z.string().regex(/^[a-z][a-z0-9]*$/, {
    message: 'Product ID must be lowercase alphanumeric, starting with letter',
  }),
  name: z.string().min(1).max(50),
  displayName: z.string().min(1).max(50),
  bundleId: z.string().regex(/^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$/, {
    message: 'Bundle ID must be valid reverse-DNS format',
  }),
  domain: z.string().regex(/^[a-z0-9-]+\.[a-z]{2,}$/, {
    message: 'Domain must be valid format like "product.app"',
  }),

  // Optional metadata
  description: z.string().max(200).optional(),
  platforms: z.array(PlatformSchema).default(['web']),
  version: z.string().regex(/^\d+\.\d+\.\d+$/).optional(),

  // Theming (optional, uses defaults if not specified)
  theme: ThemeSchema.partial().optional(),

  // Feature flags (optional)
  features: z.record(
    z.string(),
    z.boolean().or(z.string()).or(z.number())
  ).optional(),

  // Cosmos containers (optional)
  cosmos: z.object({
    containers: z.array(ContainerDefSchema).default([]),
  }).optional(),

  // Feature flags with defaults (optional)
  flags: z.array(FeatureFlagSchema).default([]),

  // Port configuration (optional)
  ports: PortConfigSchema.optional(),
});

/**
 * Extended manifest that allows additional unknown keys
 * Use this when you need to access custom fields not in the schema
 */
export const ExtendedProductManifestSchema = ProductManifestSchema.passthrough();

/**
 * Inferred TypeScript type for ProductManifest
 */
export type ProductManifest = z.infer<typeof ProductManifestSchema>;
export type Platform = z.infer<typeof PlatformSchema>;
export type Theme = z.infer<typeof ThemeSchema>;
export type ContainerDef = z.infer<typeof ContainerDefSchema>;
export type FeatureFlag = z.infer<typeof FeatureFlagSchema>;
export type PortConfig = z.infer<typeof PortConfigSchema>;

/**
 * Default theme colors (ByteLyst brand palette)
 */
export const DEFAULT_THEME: Theme = {
  primary: '#5AE68C',
  secondary: '#5A8CFF',
  accent: '#2EE6D6',
  background: '#06070A',
  surface: '#121725',
  text: '#EFF4FF',
  error: '#FF6E6E',
  warning: '#F59E0B',
  success: '#34D399',
};

/**
 * Load and validate a product manifest from a file path
 *
 * @param path Path to product.json file
 * @returns Validated ProductManifest
 * @throws ZodError if validation fails
 *
 * @example
 * ```ts
 * const manifest = await loadProductManifest('./product.json');
 * console.log(manifest.id); // 'lysnrai'
 * ```
 */
export async function loadProductManifest(path: string): Promise<ProductManifest> {
  const fs = await import('fs/promises');
  const content = await fs.readFile(path, 'utf-8');
  const json = JSON.parse(content);
  return ProductManifestSchema.parse(json);
}

/**
 * Synchronous version of loadProductManifest (for startup use)
 *
 * @param path Path to product.json file
 * @returns Validated ProductManifest
 * @throws ZodError if validation fails
 */
export function loadProductManifestSync(path: string): ProductManifest {
  const fs = require('fs');
  const content = fs.readFileSync(path, 'utf-8');
  const json = JSON.parse(content);
  return ProductManifestSchema.parse(json);
}

/**
 * Merge manifest theme with defaults
 *
 * @param manifest Product manifest
 * @returns Complete theme with defaults filled in
 */
export function resolveTheme(manifest: ProductManifest): Theme {
  return {
    ...DEFAULT_THEME,
    ...manifest.theme,
  };
}

/**
 * Validate a product manifest object without loading from file
 *
 * @param json Parsed JSON object
 * @returns Validated ProductManifest
 * @throws ZodError if validation fails
 */
export function validateProductManifest(json: unknown): ProductManifest {
  return ProductManifestSchema.parse(json);
}

/**
 * Safe validation that returns null on failure
 *
 * @param json Parsed JSON object
 * @returns Validated ProductManifest or null
 */
export function safeValidateProductManifest(json: unknown): ProductManifest | null {
  const result = ProductManifestSchema.safeParse(json);
  return result.success ? result.data : null;
}
