/**
 * CSV import parser helpers.
 *
 * Extracted from app/api/import/parse/route.ts so the helpers are
 * testable in isolation. The route file imports from here; behavior
 * is byte-identical.
 */

/** CSV shorthand -> canonical exercise name. */
export const NAME_MAP: Record<string, string> = {
  'Ab Wheel': 'Ab Wheel Rollout',
  'BB Upright Row': 'Upright Row',
  'Ball Situp': 'Exercise Ball Situp',
  Bench: 'Bench Press',
  'DB Lateral Raise': 'Lateral Raise',
  Dip: 'Dips (Chest)',
  'Face Pull': 'Face Pulls',
  'SA Lat Pulldown': 'Lat Pulldown',
  'SL Calf Raise': 'Calf Raise',
  'BB Row': 'Barbell Row',
  'DB Row': 'Dumbbell Row',
  GHD: 'Glute ham developer',
  'Hamstring DL': 'Hamstring deadlift',
  'BB Curl': 'Barbell Curl',
  'BB Hip Bridge': 'Hip Thrust',
  'Cable Trap': 'Rear delt',
  'Chinup (Narrow)': 'Chinup',
  'Chinup Negatives': 'Chinup',
  'Squat (Foot Elevated)': 'Squat',
  'Ball Bicep Curl': 'Dumbbell Curl',
  'KB Hip Flexor': 'Hip Flexor',
  'Hamstring Deadlift': 'Hamstring deadlift',
  'Shoulder Press': 'Overhead Press',
  CoC: 'Captains of Crush',
  'Hex DL': 'Hex Bar Deadlift',
  'KB Extension': 'Kettlebell Leg Extension',
  Ski: 'SkiErg',
};

/**
 * Minimal RFC 4180-ish CSV parser. Supports quoted fields, embedded
 * commas, embedded newlines inside quotes, and "" -> " escaping.
 * First row is the header (case-folded). Returns an array of
 * row-objects keyed by column name; empty cells are omitted.
 */
export function parseCSV(content: string): Array<Record<string, string>> {
  const text = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
  if (!text.trim()) return [];

  const parsedRows: string[][] = [];
  let row: string[] = [];
  let cell = '';
  let inQuotes = false;

  for (let i = 0; i < text.length; i++) {
    const ch = text[i];
    const next = text[i + 1];

    if (ch === '"') {
      if (inQuotes && next === '"') {
        cell += '"';
        i++;
      } else {
        inQuotes = !inQuotes;
      }
      continue;
    }

    if (ch === ',' && !inQuotes) {
      row.push(cell);
      cell = '';
      continue;
    }

    if (ch === '\n' && !inQuotes) {
      row.push(cell);
      if (row.some((v) => v.trim() !== '')) {
        parsedRows.push(row);
      }
      row = [];
      cell = '';
      continue;
    }

    cell += ch;
  }

  row.push(cell);
  if (row.some((v) => v.trim() !== '')) {
    parsedRows.push(row);
  }

  if (parsedRows.length === 0) return [];

  const header = parsedRows[0].map((h) => h.trim().toLowerCase());
  const rows: Array<Record<string, string>> = [];

  for (let i = 1; i < parsedRows.length; i++) {
    const values = parsedRows[i];
    const out: Record<string, string> = {};
    header.forEach((col, idx) => {
      const value = (values[idx] || '').trim();
      if (value !== '') {
        out[col] = value;
      }
    });
    if (Object.keys(out).length > 0) {
      rows.push(out);
    }
  }

  return rows;
}

export function parseFloatMaybe(value?: string): number | undefined {
  if (!value) return undefined;
  const n = Number.parseFloat(value);
  return Number.isFinite(n) ? n : undefined;
}

export function parseIntMaybe(value?: string): number | undefined {
  if (!value) return undefined;
  const n = Number.parseInt(value, 10);
  return Number.isFinite(n) ? n : undefined;
}

/** Extract a variation note from a CSV exercise name like "Squat (Foot Elevated)". */
export function getVariationNote(originalName: string): string | null {
  if (originalName.includes('Narrow')) return 'narrow';
  if (originalName.includes('Negatives')) return 'negatives';
  if (originalName.includes('Foot Elevated')) return 'foot elevated';
  return null;
}

/** Map a CSV-shorthand exercise name to its canonical name, or pass through. */
export function resolveExerciseName(csvName: string): string {
  return NAME_MAP[csvName] ?? csvName;
}

/**
 * Parse "M/D/YYYY" or "YYYY-MM-DD" into an ISO timestamp at noon UTC.
 * Noon-UTC anchors the day to a single calendar date regardless of the
 * viewer's timezone — picking 00:00 UTC would put the day on the
 * previous date for any negative-offset zone.
 */
export function parseDate(dateStr: string): string {
  const mdyMatch = dateStr.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
  if (mdyMatch) {
    const month = mdyMatch[1].padStart(2, '0');
    const day = mdyMatch[2].padStart(2, '0');
    const year = mdyMatch[3];
    return `${year}-${month}-${day}T12:00:00.000Z`;
  }
  if (dateStr.includes('-')) {
    return new Date(dateStr + 'T12:00:00.000Z').toISOString();
  }
  return new Date(dateStr).toISOString();
}
