import type { DailySummary, DecimalMacroRemaining, MacroRemaining } from '@/types/diet.types';

const EMPTY_INT_MACRO: MacroRemaining = {
  consumed: 0,
  goal: null,
  remaining: null,
  progressPercent: null,
};

const EMPTY_DECIMAL_MACRO: DecimalMacroRemaining = {
  consumed: 0,
  goal: null,
  remaining: null,
  progressPercent: null,
};

function pick<T>(raw: Record<string, unknown>, camel: string, pascal: string): T | undefined {
  return (raw[camel] ?? raw[pascal]) as T | undefined;
}

function normalizeIntMacro(raw: unknown): MacroRemaining {
  if (!raw || typeof raw !== 'object') return { ...EMPTY_INT_MACRO };
  const obj = raw as Record<string, unknown>;
  return {
    goal: (pick<number | null>(obj, 'goal', 'Goal') ?? null) as number | null,
    consumed: Number(pick<number>(obj, 'consumed', 'Consumed') ?? 0),
    remaining: (pick<number | null>(obj, 'remaining', 'Remaining') ?? null) as number | null,
    progressPercent: (pick<number | null>(obj, 'progressPercent', 'ProgressPercent') ?? null) as
      | number
      | null,
  };
}

function normalizeDecimalMacro(raw: unknown): DecimalMacroRemaining {
  if (!raw || typeof raw !== 'object') return { ...EMPTY_DECIMAL_MACRO };
  const obj = raw as Record<string, unknown>;
  return {
    goal: (pick<number | null>(obj, 'goal', 'Goal') ?? null) as number | null,
    consumed: Number(pick<number>(obj, 'consumed', 'Consumed') ?? 0),
    remaining: (pick<number | null>(obj, 'remaining', 'Remaining') ?? null) as number | null,
    progressPercent: (pick<number | null>(obj, 'progressPercent', 'ProgressPercent') ?? null) as
      | number
      | null,
  };
}

export function normalizeDailySummary(raw: unknown): DailySummary {
  if (!raw || typeof raw !== 'object') {
    return {
      date: '',
      goals: null,
      calories: { ...EMPTY_INT_MACRO },
      proteinG: { ...EMPTY_DECIMAL_MACRO },
      fatG: { ...EMPTY_DECIMAL_MACRO },
      carbsG: { ...EMPTY_DECIMAL_MACRO },
      waterMl: { ...EMPTY_INT_MACRO },
      meals: [],
      drinks: [],
    };
  }

  const obj = raw as Record<string, unknown>;
  const meals = pick<unknown[]>(obj, 'meals', 'Meals');
  const drinks = pick<unknown[]>(obj, 'drinks', 'Drinks');

  return {
    date: String(pick<string>(obj, 'date', 'Date') ?? ''),
    goals: (pick(obj, 'goals', 'Goals') as DailySummary['goals']) ?? null,
    calories: normalizeIntMacro(pick(obj, 'calories', 'Calories')),
    proteinG: normalizeDecimalMacro(pick(obj, 'proteinG', 'ProteinG')),
    fatG: normalizeDecimalMacro(pick(obj, 'fatG', 'FatG')),
    carbsG: normalizeDecimalMacro(pick(obj, 'carbsG', 'CarbsG')),
    waterMl: normalizeIntMacro(pick(obj, 'waterMl', 'WaterMl')),
    meals: Array.isArray(meals) ? (meals as DailySummary['meals']) : [],
    drinks: Array.isArray(drinks) ? (drinks as DailySummary['drinks']) : [],
  };
}
