import type {
  PublicMlbPropContext,
  PublicPlayerProp,
  PublicPlayerPropsResponseV1,
} from '@/contracts/forecast-public';

type PerPlayerPropsLike = Pick<PublicPlayerPropsResponseV1, 'mode' | 'playerProps'>;
type PlayerPropPresenceLike = Pick<PublicPlayerProp, 'assetId'>;

export function shouldUsePerPlayerProps(
  data: ({ mode?: PerPlayerPropsLike['mode']; playerProps?: PlayerPropPresenceLike[] } | null | undefined),
): boolean {
  return data?.mode === 'per_player' && Array.isArray(data?.playerProps) && data.playerProps.length > 0;
}

export function extractMlbPropContext(payload: any): PublicMlbPropContext | null {
  const context = payload?.model_context;
  if (!context || typeof context !== 'object') return null;

  const mlbPropContext = {
    kRank: context.k_rank ?? null,
    parkFactor: context.park_factor ?? null,
    weatherImpact: context.weather_impact ?? null,
    handednessSplit: context.handedness_split ?? null,
    lineupCertainty: context.lineup_certainty ?? null,
  };

  return Object.values(mlbPropContext).some((value) => value != null) ? mlbPropContext : null;
}

export function buildUnlockedPlayerPropPatch(data: any): Record<string, any> {
  const marketLine = data.payload?.market_line_value ?? data.payload?.line ?? null;
  const projectedProbability = data.payload?.projected_probability ?? data.payload?.prob ?? null;
  const forecastDirection = normalizeForecastDirection(
    data.payload?.forecast_direction ?? data.payload?.recommendation,
  );
  return {
    locked: false,
    recommendation: data.payload?.recommendation,
    reasoning: data.payload?.reasoning,
    edge: data.payload?.edge,
    prob: data.payload?.prob,
    line: data.payload?.line,
    odds: data.payload?.odds,
    confidence: data.confidence,
    projectedOutcome: data.payload?.projected_stat_value,
    statType: data.payload?.stat_type,
    normalizedStatType: data.payload?.normalized_stat_type ?? data.payload?.stat_type,
    marketLine,
    marketLineValue: marketLine,
    projectedProbability,
    projected_stat_value: data.payload?.projected_stat_value,
    stat_type: data.payload?.stat_type,
    normalized_stat_type: data.payload?.normalized_stat_type ?? data.payload?.stat_type,
    market_line_value: marketLine,
    forecastDirection,
    signalTier: data.payload?.signal_tier ?? null,
    agreementScore: data.payload?.agreement_score ?? null,
    agreementLabel: data.payload?.agreement_label ?? null,
    agreementSources: Array.isArray(data.payload?.agreement_sources) ? data.payload.agreement_sources : null,
    marketQualityScore: data.payload?.market_quality_score ?? null,
    marketQualityLabel: data.payload?.market_quality_label ?? null,
    marketImpliedProbability: data.payload?.market_implied_probability ?? null,
    signalTableRow: data.payload?.signal_table_row ?? null,
    modelContext: data.payload?.model_context || null,
    mlbPropContext: data.mlbPropContext || extractMlbPropContext(data.payload),
  };
}

export function formatPlayerPropLabel(
  prop: string | null | undefined,
  recommendation: string | null | undefined,
  line: number | string | null | undefined,
): string {
  const rawProp = String(prop || '').trim();
  const normalizedRecommendation = String(recommendation || '').trim().toUpperCase();
  const direction = normalizedRecommendation === 'UNDER' ? 'Under' : normalizedRecommendation === 'OVER' ? 'Over' : '';
  const explicitLine = line == null || line === '' ? null : String(line).trim();

  const match = rawProp.match(/^(.+?)(?:\s+(?:Over|Under))?\s+(-?\d+(?:\.\d+)?)$/i);
  const statLabel = match?.[1]?.trim() || rawProp;
  const lineLabel = explicitLine || match?.[2] || '';

  if (!statLabel) return rawProp;
  if (!direction || !lineLabel) return rawProp || `${statLabel} ${lineLabel}`.trim();
  return `${statLabel} ${direction} ${lineLabel}`;
}

export function normalizeForecastDirection(
  value: string | null | undefined,
): 'OVER' | 'UNDER' | null {
  const normalized = String(value || '').trim().toUpperCase();
  if (normalized === 'OVER' || normalized === 'UNDER') {
    return normalized;
  }
  return null;
}
