// ABOUTME: Zod validation schemas for TAB Affiliates API responses
// ABOUTME: Ensures runtime type safety and validates data structure from external API

import { z } from 'zod';

// ============================================================================
// Common Schemas
// ============================================================================

export const ApiHeaderSchema = z.object({
  title: z.string(),
  generated_time: z.string().datetime(),
  url: z.string(),
});

export const ApiErrorResponseSchema = z.object({
  error: z.object({
    code: z.string(),
    message: z.string(),
  }),
});

// ============================================================================
// Meetings API Schemas
// ============================================================================

export const MeetingsListParamsSchema = z.object({
  enc: z.string(),
  ids: z.array(z.string()).nullable().optional(),
  date_from: z.string(),
  date_to: z.string(),
  type: z.string().optional(),
  country: z.string().optional(),
  limit: z.number().optional(),
  offset: z.number().optional(),
  futures: z.boolean().optional(),
  meeting_numbers: z.array(z.number()).nullable().optional(),
});

export const RaceSummarySchema = z.object({
  id: z.string().uuid(),
  race_number: z.number().int().positive(),
  name: z.string(),
  start_time: z.string().datetime(),
  tote_start_time: z.string().regex(/^\d{2}:\d{2}:\d{2}$/), // HH:MM:SS
  track_condition: z.string(),
  distance: z.number().int().positive(),
  weather: z.string(),
  country: z.string(),
  state: z.string(),
  status: z.string(),
});

export const MeetingSchema = z.object({
  meeting: z.string().uuid(),
  name: z.string(),
  date: z.string().datetime(),
  track_condition: z.string(),
  category: z.enum(['T', 'H', 'G']),
  category_name: z.string(),
  country: z.string(),
  state: z.string(),
  races: z.array(RaceSummarySchema),
});

export const MeetingsListResponseSchema = z.object({
  header: ApiHeaderSchema,
  params: MeetingsListParamsSchema,
  data: z.object({
    meetings: z.array(MeetingSchema),
  }),
});

export const MeetingByIdParamsSchema = z.object({
  enc: z.string(),
  id: z.string().uuid(),
});

export const MeetingByIdResponseSchema = z.object({
  header: ApiHeaderSchema,
  params: MeetingByIdParamsSchema,
  data: z.object({
    meetings: z.array(MeetingSchema).length(1), // Exactly 1 meeting expected
  }),
});

// ============================================================================
// Race/Event Detail Schemas (GET /events/:id)
// ============================================================================

export const RunnerOddsSchema = z.object({
  fixed_win: z.number().optional(),
  fixed_place: z.number().optional(),
  pool_win: z.number().optional(),
  pool_place: z.number().optional(),
});

export const OddsFlucSchema = z.object({
  timestamp: z.string(),
  fluc: z.number(),
});

export const FlucsWithTimestampSchema = z.object({
  last_six: z.array(OddsFlucSchema).optional(),
  open: OddsFlucSchema.optional(),
  high: OddsFlucSchema.optional(),
  low: OddsFlucSchema.optional(),
  nine_am: OddsFlucSchema.optional(),
});

export const RunnerWeightSchema = z.object({
  allocated: z.string().optional(),
  total: z.string().optional(),
});

export const PerformanceStatsSchema = z.object({
  number_of_starts: z.number(),
  number_of_wins: z.number(),
  number_of_placings: z.number(),
  number_of_seconds: z.number(),
  number_of_thirds: z.number(),
  winning_distance: z.number().optional(),
});

export const RunnerDetailSchema = z.object({
  entrant_id: z.string().uuid().optional(),
  market_name: z.string().optional(),
  primary_market: z.boolean().optional(),
  name: z.string(),
  is_scratched: z.boolean(),
  gear: z.string().optional(),
  odds: RunnerOddsSchema.nullable().optional(),
  scratch_time: z.number(),
  barrier: z.number(),
  runner_number: z.number(),
  prize_money: z.string().optional(),
  age: z.number().optional(),
  sex: z.string().optional(),
  colour: z.string().optional(),
  silk_colours: z.string().optional(),
  jockey: z.string().optional(),
  apprentice_indicator: z.string().optional(),
  allowance_weight: z.string().optional(),
  owners: z.string().optional(),
  country: z.string().optional(),
  trainer_name: z.string().optional(),
  trainer_location: z.string().optional(),
  last_twenty_starts: z.string().optional(),
  sire: z.string().optional(),
  dam: z.string().optional(),
  dam_sire: z.string().optional(),
  breeding: z.string().optional(),
  weight: RunnerWeightSchema.nullable().optional(),
  favourite: z.boolean().optional(),
  mover: z.boolean().optional(),
  horse_id: z.number().optional(),
  past_performances: z.object({
    jockey: PerformanceStatsSchema.optional(),
  }).nullable().optional(),
  jockey_past_performances: z.object({
    last_50_starts: PerformanceStatsSchema.optional(),
    trainer: PerformanceStatsSchema.optional(),
  }).nullable().optional(),
  fresh_90: PerformanceStatsSchema.nullable().optional(),
  flucs: z.array(z.number()).optional(),
  flucs_with_timestamp: FlucsWithTimestampSchema.nullable().optional(),
  scr_time: z.string().nullable().optional(),
  deduction: z.object({
    win: z.number(),
    place: z.number(),
  }).nullable().optional(),
});

export const RaceResultSchema = z.object({
  position: z.number(),
  name: z.string(),
  barrier: z.number(),
  runner_number: z.number(),
  margin_length: z.number(),
  entrant_id: z.string().uuid(),
});

export const DividendPositionSchema = z.object({
  runner_number: z.number(),
  position: z.number(),
});

export const DividendSchema = z.object({
  id: z.string().uuid(),
  tote: z.string(),
  product_name: z.string(),
  status: z.string(),
  dividend: z.number(),
  pool_size: z.number().optional(),
  jackpot_size: z.number().optional(),
  positions: z.array(DividendPositionSchema),
  description: z.string().optional(),
});

export const TotePoolSchema = z.object({
  product_type: z.string(),
  total: z.number(),
  status: z.string(),
  guarantee: z.number().optional(),
  brought_forward: z.number().optional(),
  terminating: z.boolean().optional(),
  jackpot: z.number().optional(),
  leg: z.number().optional(),
  is_commingled: z.boolean().optional(),
  is_concession: z.boolean().optional(),
  is_final: z.boolean().optional(),
  win_investment: z.string().optional(),
});

export const PrizeMoniesSchema = z.record(z.string(), z.number());

export const RaceDetailSchema = z.object({
  event_id: z.string().uuid(),
  meeting_name: z.string(),
  meeting_id: z.string().uuid(),
  status: z.string(),
  description: z.string(),
  advertised_start: z.number(),
  actual_start: z.number().optional(),
  advertised_start_string: z.string().optional(),
  actual_start_string: z.string().optional(),
  race_number: z.number(),
  type: z.string(),
  country: z.string(),
  state: z.string().optional(),
  distance: z.number(),
  weather: z.string().optional(),
  track_condition: z.string().optional(),
  track_direction: z.string().optional(),
  entrant_count: z.number().optional(),
  field_size: z.number().optional(),
  positions_paid: z.number().optional(),
  rail_position: z.string().optional(),
  prize_monies: PrizeMoniesSchema.optional(),
  comment: z.string().optional(),
});

export const RaceByIdParamsSchema = z.object({
  enc: z.string(),
  id: z.string().uuid(),
  present_overlay: z.boolean().optional(),
  with_big_bets: z.boolean().optional(),
  with_live_bets: z.boolean().optional(),
  with_money_tracker: z.boolean().optional(),
  with_biggest_bet: z.boolean().optional(),
  will_pays: z.boolean().optional(),
  with_tote_trends_data: z.boolean().optional(),
});

export const RaceByIdResponseSchema = z.object({
  header: ApiHeaderSchema,
  params: RaceByIdParamsSchema.optional(),
  data: z.object({
    race: RaceDetailSchema,
    results: z.array(RaceResultSchema).optional(),
    dividends: z.array(DividendSchema).optional(),
    runners: z.array(RunnerDetailSchema),
    tote_pools: z.array(TotePoolSchema).optional(),
  }),
});

// ============================================================================
// Helper Types (inferred from schemas for type safety)
// ============================================================================

export type ValidatedMeetingsListResponse = z.infer<typeof MeetingsListResponseSchema>;
export type ValidatedMeetingByIdResponse = z.infer<typeof MeetingByIdResponseSchema>;
export type ValidatedMeeting = z.infer<typeof MeetingSchema>;
export type ValidatedRaceSummary = z.infer<typeof RaceSummarySchema>;
export type ValidatedRaceByIdResponse = z.infer<typeof RaceByIdResponseSchema>;
export type ValidatedRaceDetail = z.infer<typeof RaceDetailSchema>;
export type ValidatedRunnerDetail = z.infer<typeof RunnerDetailSchema>;
export type ValidatedRaceResult = z.infer<typeof RaceResultSchema>;
export type ValidatedDividend = z.infer<typeof DividendSchema>;
export type ValidatedTotePool = z.infer<typeof TotePoolSchema>;
