import { WorkoutSession, WorkoutSet, ExerciseDef } from '../types';

/**
 * Escapes a field for CSV format (wraps in quotes if contains comma, quote or newline)
 */
const escapeCsvField = (field: any): string => {
    if (field === null || field === undefined) {
        return '';
    }
    const stringValue = String(field);
    if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
        return `"${stringValue.replace(/"/g, '""')}"`;
    }
    return stringValue;
};

export const generateCsv = (sessions: WorkoutSession[], exercises: ExerciseDef[]): string => {
    // Create a map for quick exercise lookup
    const exerciseMap = new Map<string, ExerciseDef>();
    exercises.forEach(ex => exerciseMap.set(ex.id, ex));

    const headers = [
        // Session Data
        'Session ID',
        'Session Start Time',
        'Session End Time',
        'Session Duration (Seconds)',
        'Session Date (YYYY-MM-DD)',
        'Session Note',
        'User Body Weight (kg)',
        'Plan ID',
        'Plan Name',
        'Session Type',

        // Set Data
        'Set ID',
        'Exercise ID',
        'Exercise Name',
        'Exercise Type',
        'Reps',
        'Weight (kg)',
        'Duration (Seconds)',
        'Distance (Meters)',
        'Height (cm)',
        'Body Weight Percentage',
        'Set Timestamp',
        'Set Side',
        'Set Completed',

        // Linked Exercise Data
        'Linked Exercise Is Unilateral',
        'Linked Exercise Default Rest (Seconds)',
        'Linked Exercise Default BW %',
        'Linked Exercise Archived'
    ];

    const rows: string[] = [headers.join(',')];

    // Sort sessions by date descending (though for raw data logic might not matter, usually newest first is nice, or chronological)
    // Let's stick to the order passed or sort chronologically?
    // Usually exports are chronological.
    const sortedSessions = [...sessions].sort((a, b) => a.startTime - b.startTime);

    for (const session of sortedSessions) {
        const sessionDate = new Date(session.startTime).toISOString().split('T')[0];
        const sessionDuration = session.endTime ? Math.round((session.endTime - session.startTime) / 1000) : '';

        // If session has no sets, we might still want to export it as a row? 
        // Requirements said "Link one row of the table as 1 set".
        // If no sets, maybe skip? or output one row with empty set data?
        // Let's output at least one row if empty, but usually sessions have sets.
        // If empty sets, we can't really make "one row = 1 set". 
        // But for completeness let's skip empty sessions or put nulls. Users usually have sets.

        if (session.sets.length === 0) {
            // Optional: Handle empty session
            const row = [
                session.id,
                new Date(session.startTime).toISOString(),
                session.endTime ? new Date(session.endTime).toISOString() : '',
                sessionDuration,
                sessionDate,
                session.note,
                session.userBodyWeight,
                session.planId,
                session.planName,
                session.type,
                // Empty set columns
                ...Array(headers.length - 10).fill('')
            ].map(escapeCsvField).join(',');
            rows.push(row);
            continue;
        }

        for (const set of session.sets) {
            const linkedExercise = exerciseMap.get(set.exerciseId);

            const row = [
                // Session
                session.id,
                new Date(session.startTime).toISOString(),
                session.endTime ? new Date(session.endTime).toISOString() : '',
                sessionDuration,
                sessionDate,
                session.note,
                session.userBodyWeight,
                session.planId,
                session.planName,
                session.type,

                // Set
                set.id,
                set.exerciseId,
                set.exerciseName,
                set.type,
                set.reps,
                set.weight,
                set.durationSeconds,
                set.distanceMeters,
                set.height,
                set.bodyWeightPercentage,
                new Date(set.timestamp).toISOString(),
                set.side,
                set.completed,

                // Linked Exercise
                linkedExercise?.isUnilateral,
                linkedExercise?.defaultRestSeconds,
                linkedExercise?.bodyWeightPercentage,
                linkedExercise?.isArchived
            ].map(escapeCsvField).join(',');

            rows.push(row);
        }
    }

    return rows.join('\n');
};

export const downloadCsv = (content: string, baseFilename: string = 'gymflow_history') => {
    const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    const url = URL.createObjectURL(blob);

    // Create filename with current date
    const dateStr = new Date().toISOString().split('T')[0];
    const filename = `${baseFilename}_${dateStr}.csv`;

    link.setAttribute('href', url);
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
};
