import { getPlayerPropTypeLabel } from './player-prop-signals';

function toFiniteNumber(value: any): number | null {
  if (value == null || value === '') return null;
  const numeric = Number(value);
  return Number.isFinite(numeric) ? numeric : null;
}

function formatStoredPlayerPropLine(value: number | null | undefined): string | null {
  const numeric = toFiniteNumber(value);
  return numeric == null ? null : String(numeric);
}

export function buildStoredPlayerPropDisplayFields(params: {
  league: string;
  propText?: string | null;
  statType?: string | null;
  normalizedStatType?: string | null;
  forecastDirection?: string | null;
  marketLine?: number | null;
  odds?: number | null;
}): {
  prop: string | null;
  forecast: string | null;
  propType: string;
  sportsbookDisplay: string | null;
} {
  const propType = getPlayerPropTypeLabel({
    league: params.league,
    prop: params.propText ?? null,
    statType: params.statType ?? null,
    normalizedStatType: params.normalizedStatType ?? params.statType ?? null,
  });
  const direction = String(params.forecastDirection || '').trim().toUpperCase();
  const directionLabel = direction === 'UNDER' ? 'Under' : direction === 'OVER' ? 'Over' : null;
  const lineLabel = formatStoredPlayerPropLine(params.marketLine);
  const normalizedProp = propType && directionLabel && lineLabel
    ? `${propType} ${directionLabel} ${lineLabel}`
    : (typeof params.propText === 'string' && params.propText.trim()) || null;
  const odds = toFiniteNumber(params.odds);
  const sportsbookDisplay = normalizedProp
    ? odds != null ? `${normalizedProp} (${odds > 0 ? '+' : ''}${odds})` : normalizedProp
    : null;

  return {
    prop: normalizedProp,
    forecast: normalizedProp,
    propType,
    sportsbookDisplay,
  };
}

export function shouldPersistStandalonePlayerPropMetadata(prop: {
  forecast_direction?: string | null;
  agreement_score?: number | null;
  market_quality_label?: string | null;
}): boolean {
  return Boolean(prop.forecast_direction)
    && prop.agreement_score != null
    && Boolean(prop.market_quality_label);
}

export function shouldRenderTeamPropBundleEntry(prop: {
  player?: string | null;
  prop?: string | null;
  prob?: number | null;
  projected_probability?: number | null;
  line?: number | null;
  market_line_value?: number | null;
  forecast_direction?: string | null;
  agreement_score?: number | null;
  market_quality_label?: string | null;
}): boolean {
  const hasPlayer = Boolean(String(prop.player || '').trim());
  const hasProp = Boolean(String(prop.prop || '').trim());
  const hasProbability = toFiniteNumber(prop.projected_probability ?? prop.prob) != null;
  const hasLine = toFiniteNumber(prop.market_line_value ?? prop.line) != null;
  return hasPlayer
    && hasProp
    && hasProbability
    && hasLine
    && shouldPersistStandalonePlayerPropMetadata(prop);
}

export function buildStoredPlayerPropPayload(params: {
  assetMetadata?: Record<string, any>;
  league: string;
  playerName: string;
  statType?: string | null;
  normalizedStatType?: string | null;
  prop: Record<string, any>;
}): Record<string, any> {
  const displayFields = buildStoredPlayerPropDisplayFields({
    league: params.league,
    propText: params.prop.prop ?? null,
    statType: params.statType ?? null,
    normalizedStatType: params.normalizedStatType ?? params.statType ?? null,
    forecastDirection: params.prop.forecast_direction ?? params.prop.recommendation ?? null,
    marketLine: params.prop.market_line_value ?? null,
    odds: params.prop.odds ?? null,
  });

  return {
    ...(params.assetMetadata || {}),
    player: params.playerName,
    prop: displayFields.prop,
    forecast: displayFields.forecast,
    prop_type: displayFields.propType,
    sportsbook_display: displayFields.sportsbookDisplay,
    recommendation: params.prop.recommendation,
    reasoning: params.prop.reasoning,
    edge: params.prop.edge ?? null,
    edge_pct: params.prop.edge_pct ?? params.prop.edge ?? null,
    prob: params.prop.prob ?? null,
    projected_probability: params.prop.projected_probability ?? params.prop.prob ?? null,
    market_implied_probability: params.prop.market_implied_probability ?? null,
    signal_tier: params.prop.signal_tier ?? null,
    signal_label: params.prop.signal_label ?? null,
    forecast_direction: params.prop.forecast_direction ?? null,
    agreement_score: params.prop.agreement_score ?? null,
    agreement_label: params.prop.agreement_label ?? null,
    agreement_sources: params.prop.agreement_sources ?? [],
    market_source: params.prop.market_source ?? null,
    market_quality_score: params.prop.market_quality_score ?? null,
    market_quality_label: params.prop.market_quality_label ?? null,
    market_completeness_status: params.prop.market_completeness_status ?? null,
    line: params.prop.market_line_value ?? null,
    market_line_value: params.prop.market_line_value ?? null,
    projected_stat_value: params.prop.projected_stat_value ?? null,
    stat_type: params.statType ?? null,
    normalized_stat_type: params.normalizedStatType ?? params.statType ?? null,
    odds: params.prop.odds ?? null,
    player_role: params.prop.player_role ?? null,
    source_backed: params.prop.source_backed ?? true,
    grading_category: 'PLAYER_PROPS',
    signal_table_row: params.prop.signal_table_row ?? null,
    model_context: params.prop.model_context ?? null,
  };
}
