/**
 * Database Types and Utilities
 * Type helpers for working with Prisma and the database
 */

import type { Prisma } from '@prisma/client';

// Re-export Prisma types for convenience
export type {
  User,
  Plant,
  TransportEvent,
  VerticalFarm,
  GrowingZone,
  CropBatch,
  GrowingRecipe,
  SeedBatch,
  HarvestBatch,
  ConsumerPreference,
  DemandSignal,
  SupplyCommitment,
  MarketMatch,
  SeasonalPlan,
  DemandForecast,
  PlantingRecommendation,
  ResourceUsage,
  FarmAnalytics,
  AuditLog,
  BlockchainBlock,
} from '@prisma/client';

// Common query options
export interface PaginationOptions {
  page?: number;
  limit?: number;
  cursor?: string;
}

export interface SortOptions {
  field: string;
  direction: 'asc' | 'desc';
}

// Location-based query options
export interface LocationFilter {
  latitude: number;
  longitude: number;
  radiusKm: number;
}

// Date range filter
export interface DateRangeFilter {
  start: Date;
  end: Date;
}

// Create input types for common operations
export type CreateUserInput = Prisma.UserCreateInput;
export type UpdateUserInput = Prisma.UserUpdateInput;

export type CreatePlantInput = Prisma.PlantCreateInput;
export type UpdatePlantInput = Prisma.PlantUpdateInput;

export type CreateTransportEventInput = Prisma.TransportEventCreateInput;
export type UpdateTransportEventInput = Prisma.TransportEventUpdateInput;

export type CreateVerticalFarmInput = Prisma.VerticalFarmCreateInput;
export type UpdateVerticalFarmInput = Prisma.VerticalFarmUpdateInput;

export type CreateCropBatchInput = Prisma.CropBatchCreateInput;
export type UpdateCropBatchInput = Prisma.CropBatchUpdateInput;

// Result types with includes
export type PlantWithOwner = Prisma.PlantGetPayload<{
  include: { owner: true };
}>;

export type PlantWithLineage = Prisma.PlantGetPayload<{
  include: {
    owner: true;
    parentPlant: true;
    childPlants: true;
  };
}>;

export type TransportEventWithParties = Prisma.TransportEventGetPayload<{
  include: {
    sender: true;
    receiver: true;
    plants: true;
  };
}>;

export type VerticalFarmWithZones = Prisma.VerticalFarmGetPayload<{
  include: {
    owner: true;
    zones: true;
    cropBatches: true;
  };
}>;

// Utility type for pagination results
export interface PaginatedResult<T> {
  items: T[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
  hasMore: boolean;
}

// Helper function to calculate distance between two points (Haversine formula)
export function calculateDistanceKm(
  lat1: number,
  lon1: number,
  lat2: number,
  lon2: number
): number {
  const R = 6371; // Earth's radius in km
  const dLat = toRad(lat2 - lat1);
  const dLon = toRad(lon2 - lon1);
  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  return R * c;
}

function toRad(deg: number): number {
  return deg * (Math.PI / 180);
}

// Helper to create pagination result
export function createPaginatedResult<T>(
  items: T[],
  total: number,
  page: number,
  limit: number
): PaginatedResult<T> {
  const totalPages = Math.ceil(total / limit);
  return {
    items,
    total,
    page,
    limit,
    totalPages,
    hasMore: page < totalPages,
  };
}
