/**
 * Type Conversion Utilities
 * 
 * This module provides type-safe conversion functions for handling:
 * - Database nulls → Application undefined
 * - Json types → Form data types
 * - Type guards for runtime validation
 * 
 * These utilities eliminate the need for `as any` casts by providing
 * explicit, type-safe conversions at data boundaries.
 */

import type { Json } from '@/integrations/supabase/types';

/**
 * Convert database null to application undefined
 * Database returns null, but forms expect undefined for optional fields
 */
export function nullToUndefined<T>(value: T | null): T | undefined {
  return value === null ? undefined : value;
}

/**
 * Convert all null values in an object to undefined
 * Use at database boundaries when fetching data for forms
 */
export function convertNullsToUndefined<T extends Record<string, unknown>>(
  obj: T
): { [K in keyof T]: T[K] extends (infer U | null) ? (U | undefined) : T[K] } {
  const result: Record<string, unknown> = {};
  for (const key in obj) {
    const value = obj[key];
    result[key] = value === null ? undefined : value;
  }
  return result as { [K in keyof T]: T[K] extends (infer U | null) ? (U | undefined) : T[K] };
}

/**
 * Photo item interface for type-safe photo handling
 */
export interface PhotoItem {
  url: string;
  caption?: string;
  title?: string;
  cloudflare_id?: string;
  order_index?: number;
}

/**
 * Type guard: Check if value is a valid photo array
 */
export function isPhotoArray(data: unknown): data is PhotoItem[] {
  return (
    Array.isArray(data) &&
    data.every(
      (item) =>
        typeof item === 'object' &&
        item !== null &&
        'url' in item &&
        typeof (item as Record<string, unknown>).url === 'string'
    )
  );
}

/**
 * Safely extract photo array from Json data
 * Handles both direct arrays and nested { photos: [...] } structures
 */
export function extractPhotoArray(data: Json): PhotoItem[] {
  // Direct array
  if (isPhotoArray(data)) {
    return data;
  }

  // Nested photos property
  if (typeof data === 'object' && data !== null && !Array.isArray(data)) {
    const obj = data as Record<string, Json>;
    if ('photos' in obj && isPhotoArray(obj.photos)) {
      return obj.photos;
    }
  }

  return [];
}

/**
 * Type guard: Check if Json is a plain object (not array or null)
 */
export function isJsonObject(data: Json): data is Record<string, Json> {
  return typeof data === 'object' && data !== null && !Array.isArray(data);
}

/**
 * Convert Json to a form-compatible object
 * Converts all null values to undefined for form compatibility
 */
export function jsonToFormData(data: Json | unknown): Record<string, unknown> {
  if (!isJsonObject(data as Json)) {
    return {};
  }

  const result: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(data as Record<string, Json>)) {
    result[key] = value === null ? undefined : value;
  }

  return result;
}

/**
 * Type guard: Check if object has a specific property with a given type
 */
export function hasProperty<T>(
  obj: unknown,
  key: string,
  typeCheck: (value: unknown) => value is T
): obj is Record<string, unknown> & { [K in typeof key]: T } {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    key in obj &&
    typeCheck((obj as Record<string, unknown>)[key])
  );
}

/**
 * Safely get a property from Json with type assertion
 */
export function getProperty<T = unknown>(
  data: Json,
  key: string,
  defaultValue?: T
): T | undefined {
  if (isJsonObject(data) && key in data) {
    const value = data[key];
    return value === null ? defaultValue : (value as T);
  }
  return defaultValue;
}

/**
 * Convert array of database records with nulls to form-compatible records
 * Useful when fetching lists of entities for display/editing
 */
export function convertArrayNullsToUndefined<T extends Record<string, unknown>>(
  arr: T[]
): Array<{ [K in keyof T]: T[K] extends (infer U | null) ? (U | undefined) : T[K] }> {
  return arr.map((item) => convertNullsToUndefined(item));
}
