/**
 * Runtime Type Validation
 * 
 * Validates data from Supabase queries at runtime to ensure type safety.
 * Uses Zod schemas to parse and validate database responses.
 */

import { z } from 'zod';
import type { Park, Ride, Company, RideModel } from '@/types/database';

// ============================================
// RUNTIME SCHEMAS (Mirror Database Types)
// ============================================

export const parkRuntimeSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  slug: z.string(),
  description: z.string().nullable().optional(),
  park_type: z.string(),
  status: z.enum(['operating', 'closed_permanently', 'closed_temporarily', 'under_construction', 'planned', 'abandoned']),
  opening_date: z.string().nullable().optional(),
  opening_date_precision: z.string().nullable().optional(),
  closing_date: z.string().nullable().optional(),
  closing_date_precision: z.string().nullable().optional(),
  location_id: z.string().uuid().nullable().optional(),
  operator_id: z.string().uuid().nullable().optional(),
  property_owner_id: z.string().uuid().nullable().optional(),
  website_url: z.string().nullable().optional(),
  phone: z.string().nullable().optional(),
  email: z.string().nullable().optional(),
  banner_image_url: z.string().nullable().optional(),
  banner_image_id: z.string().nullable().optional(),
  card_image_url: z.string().nullable().optional(),
  card_image_id: z.string().nullable().optional(),
  ride_count: z.number().optional(),
  coaster_count: z.number().optional(),
  average_rating: z.number().nullable().optional(),
  review_count: z.number().optional(),
  view_count_7d: z.number().optional(),
  view_count_30d: z.number().optional(),
  view_count_all: z.number().optional(),
  created_at: z.string().optional(),
  updated_at: z.string().optional(),
}).passthrough(); // Allow additional fields from joins

export const rideRuntimeSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  slug: z.string(),
  description: z.string().nullable().optional(),
  category: z.string(),
  ride_sub_type: z.string().nullable().optional(),
  status: z.enum(['operating', 'closed_permanently', 'closed_temporarily', 'under_construction', 'relocated', 'stored', 'demolished']),
  park_id: z.string().uuid().nullable().optional(),
  manufacturer_id: z.string().uuid().nullable().optional(),
  designer_id: z.string().uuid().nullable().optional(),
  ride_model_id: z.string().uuid().nullable().optional(),
  opening_date: z.string().nullable().optional(),
  opening_date_precision: z.string().nullable().optional(),
  closing_date: z.string().nullable().optional(),
  closing_date_precision: z.string().nullable().optional(),
  height_requirement_cm: z.number().nullable().optional(),
  age_requirement: z.number().nullable().optional(),
  max_speed_kmh: z.number().nullable().optional(),
  duration_seconds: z.number().nullable().optional(),
  capacity_per_hour: z.number().nullable().optional(),
  gforce_max: z.number().nullable().optional(),
  inversions_count: z.number().nullable().optional(),
  length_meters: z.number().nullable().optional(),
  height_meters: z.number().nullable().optional(),
  drop_meters: z.number().nullable().optional(),
  angle_degrees: z.number().nullable().optional(),
  coaster_type: z.string().nullable().optional(),
  seating_type: z.string().nullable().optional(),
  intensity_level: z.string().nullable().optional(),
  former_names: z.array(z.unknown()).nullable().optional(),
  banner_image_url: z.string().nullable().optional(),
  banner_image_id: z.string().nullable().optional(),
  card_image_url: z.string().nullable().optional(),
  card_image_id: z.string().nullable().optional(),
  average_rating: z.number().nullable().optional(),
  review_count: z.number().optional(),
  view_count_7d: z.number().optional(),
  view_count_30d: z.number().optional(),
  view_count_all: z.number().optional(),
  created_at: z.string().optional(),
  updated_at: z.string().optional(),
}).passthrough();

export const companyRuntimeSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  slug: z.string(),
  description: z.string().nullable().optional(),
  company_type: z.string(),
  person_type: z.string().nullable().optional(),
  founded_year: z.number().nullable().optional(),
  founded_date: z.string().nullable().optional(),
  founded_date_precision: z.string().nullable().optional(),
  headquarters_location: z.string().nullable().optional(),
  website_url: z.string().nullable().optional(),
  logo_url: z.string().nullable().optional(),
  banner_image_url: z.string().nullable().optional(),
  banner_image_id: z.string().nullable().optional(),
  card_image_url: z.string().nullable().optional(),
  card_image_id: z.string().nullable().optional(),
  average_rating: z.number().nullable().optional(),
  review_count: z.number().optional(),
  view_count_7d: z.number().optional(),
  view_count_30d: z.number().optional(),
  view_count_all: z.number().optional(),
  created_at: z.string().optional(),
  updated_at: z.string().optional(),
}).passthrough();

export const rideModelRuntimeSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  slug: z.string(),
  manufacturer_id: z.string().uuid().nullable().optional(),
  category: z.string(),
  description: z.string().nullable().optional(),
  // Note: technical_specs deprecated - use ride_model_technical_specifications table
  created_at: z.string().optional(),
  updated_at: z.string().optional(),
}).passthrough();

// ============================================
// VALIDATION HELPERS
// ============================================

/**
 * Validate a single park record
 */
export function validatePark(data: unknown): Park {
  return parkRuntimeSchema.parse(data) as Park;
}

/**
 * Validate an array of park records
 */
export function validateParks(data: unknown): Park[] {
  return z.array(parkRuntimeSchema).parse(data) as Park[];
}

/**
 * Safely validate parks (returns null on error)
 */
export function safeValidateParks(data: unknown): Park[] | null {
  const result = z.array(parkRuntimeSchema).safeParse(data);
  return result.success ? (result.data as Park[]) : null;
}

/**
 * Validate a single ride record
 */
export function validateRide(data: unknown): Ride {
  return rideRuntimeSchema.parse(data) as Ride;
}

/**
 * Validate an array of ride records
 */
export function validateRides(data: unknown): Ride[] {
  return z.array(rideRuntimeSchema).parse(data) as Ride[];
}

/**
 * Safely validate rides (returns null on error)
 */
export function safeValidateRides(data: unknown): Ride[] | null {
  const result = z.array(rideRuntimeSchema).safeParse(data);
  return result.success ? (result.data as Ride[]) : null;
}

/**
 * Validate a single company record
 */
export function validateCompany(data: unknown): Company {
  return companyRuntimeSchema.parse(data) as Company;
}

/**
 * Validate an array of company records
 */
export function validateCompanies(data: unknown): Company[] {
  return z.array(companyRuntimeSchema).parse(data) as Company[];
}

/**
 * Safely validate companies (returns null on error)
 */
export function safeValidateCompanies(data: unknown): Company[] | null {
  const result = z.array(companyRuntimeSchema).safeParse(data);
  return result.success ? (result.data as Company[]) : null;
}

/**
 * Validate a single ride model record
 */
export function validateRideModel(data: unknown): RideModel {
  return rideModelRuntimeSchema.parse(data) as RideModel;
}

/**
 * Validate an array of ride model records
 */
export function validateRideModels(data: unknown): RideModel[] {
  return z.array(rideModelRuntimeSchema).parse(data) as RideModel[];
}

/**
 * Safely validate ride models (returns null on error)
 */
export function safeValidateRideModels(data: unknown): RideModel[] | null {
  const result = z.array(rideModelRuntimeSchema).safeParse(data);
  return result.success ? (result.data as RideModel[]) : null;
}

/**
 * Generic validator for any entity type
 */
export function validateEntity<T>(
  data: unknown, 
  schema: z.ZodSchema<T>
): T {
  return schema.parse(data);
}

/**
 * Safe generic validator (returns null on error)
 */
export function safeValidateEntity<T>(
  data: unknown,
  schema: z.ZodSchema<T>
): T | null {
  const result = schema.safeParse(data);
  return result.success ? result.data : null;
}
