
import React, { useState } from 'react';
import { createPortal } from 'react-dom';
import { useNavigate } from 'react-router-dom';
import { Trash2, Calendar, Clock, ChevronDown, ChevronUp, History as HistoryIcon, Dumbbell, Ruler, Timer, Weight, Edit2, Gauge, Pencil, Save, MoreVertical, ClipboardList, Download } from 'lucide-react';
import { TopBar } from './ui/TopBar';
import { WorkoutSession, ExerciseType, WorkoutSet, Language } from '../types';
import { t } from '../services/i18n';
import { formatSetMetrics } from '../utils/setFormatting';
import { useSession } from '../context/SessionContext';
import { generateCsv, downloadCsv } from '../utils/csvExport';
import { useAuth } from '../context/AuthContext';
import { getExercises } from '../services/storage';
import { Button } from './ui/Button';
import { Ripple } from './ui/Ripple';
import { Card } from './ui/Card';
import { Modal } from './ui/Modal';
import { SideSheet } from './ui/SideSheet';
import EditSetModal from './EditSetModal';
import FilledInput from './FilledInput';

interface HistoryProps {
    lang: Language;
}

const History: React.FC<HistoryProps> = ({ lang }) => {
    const { sessions, updateSession, deleteSession } = useSession();
    const { currentUser } = useAuth();
    const userId = currentUser?.id || '';
    const navigate = useNavigate();
    const [exercises, setExercises] = useState<import('../types').ExerciseDef[]>([]);

    const [editingSession, setEditingSession] = useState<WorkoutSession | null>(null);
    const [menuState, setMenuState] = useState<{ id: string, x: number, y: number } | null>(null);

    const [deletingId, setDeletingId] = useState<string | null>(null);
    const [deletingSetInfo, setDeletingSetInfo] = useState<{ sessionId: string, setId: string } | null>(null);
    const [editingSetInfo, setEditingSetInfo] = useState<{ sessionId: string, set: WorkoutSet } | null>(null);

    const handleSaveSingleSet = async (updatedSet: WorkoutSet) => {
        if (!editingSetInfo) return;
        const session = sessions.find(s => s.id === editingSetInfo.sessionId);
        if (session) {
            const updatedSets = session.sets.map(s => s.id === updatedSet.id ? updatedSet : s);
            const updatedSession = { ...session, sets: updatedSets };
            try {
                await updateSession(updatedSession);
                setEditingSetInfo(null);
            } catch (e) {
                console.error("Failed to update set", e);
            }
        }
    };

    const handleSaveSetFromModal = async (updatedSet: WorkoutSet) => {
        if (!editingSetInfo) return;

        // If editing within the session edit modal, update local state only
        if (editingSession && editingSession.id === editingSetInfo.sessionId) {
            const updatedSets = editingSession.sets.map(s =>
                s.id === updatedSet.id ? updatedSet : s
            );
            setEditingSession({ ...editingSession, sets: updatedSets });
            setEditingSetInfo(null);
        } else {
            // Otherwise save to backend (Quick Log flow)
            await handleSaveSingleSet(updatedSet);
        }
    };

    React.useEffect(() => {
        if (!userId) return;
        getExercises(userId).then(exs => setExercises(exs));
    }, [userId]);


    const calculateSessionWork = (session: WorkoutSession) => {
        const bw = session.userBodyWeight || 70;
        return session.sets.reduce((acc, set) => {
            let w = 0;
            if (set.type === ExerciseType.STRENGTH) {
                w = (set.weight || 0) * (set.reps || 0);
            }
            if (set.type === ExerciseType.BODYWEIGHT) {
                const percent = set.bodyWeightPercentage || 100;
                const effectiveBw = bw * (percent / 100);
                w = (effectiveBw + (set.weight || 0)) * (set.reps || 0);
            }
            return acc + Math.max(0, w);
        }, 0);
    };

    const formatDateForInput = (timestamp: number) => {
        const d = new Date(timestamp);
        const pad = (n: number) => (n < 10 ? '0' + n : n);
        return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
    };

    const parseDateFromInput = (value: string) => {
        return new Date(value).getTime();
    };

    const formatDuration = (startTime: number, endTime?: number) => {
        if (!endTime || isNaN(endTime) || isNaN(startTime)) return '';
        const durationMs = endTime - startTime;
        if (durationMs < 0 || isNaN(durationMs)) return '';

        const hours = Math.floor(durationMs / 3600000);
        const minutes = Math.floor((durationMs % 3600000) / 60000);

        if (hours > 0) {
            return `${hours}h ${minutes}m`;
        }
        if (minutes < 1) {
            return '<1m';
        }
        return `${minutes}m`;
    };


    const handleSaveEdit = async () => {
        if (editingSession) {
            try {
                await updateSession(editingSession);
                setEditingSession(null);
            } catch (e) {
                console.error("Failed to update session", e);
            }
        }
    };



    const handleDeleteSet = (setId: string) => {
        if (!editingSession) return;
        setEditingSession({
            ...editingSession,
            sets: editingSession.sets.filter(s => s.id !== setId)
        });
    };

    const handleConfirmDelete = async () => {
        if (deletingId) {
            try {
                await deleteSession(deletingId);
                setDeletingId(null);
            } catch (e) {
                console.error("Failed to delete session", e);
            }
        } else if (deletingSetInfo) {
            // Find the session
            const session = sessions.find(s => s.id === deletingSetInfo.sessionId);
            if (session) {
                // Create updated session with the set removed
                const updatedSession = {
                    ...session,
                    sets: session.sets.filter(s => s.id !== deletingSetInfo.setId)
                };
                try {
                    await updateSession(updatedSession);
                } catch (e) {
                    console.error("Failed to update session after set delete", e);
                }
            }
            setDeletingSetInfo(null);
        }
    }


    if (sessions.length === 0) {
        return (
            <div className="flex flex-col items-center justify-center h-full text-on-surface-variant p-8 text-center">
                <Clock size={48} className="mb-4 opacity-50" />
                <p>{t('history_empty', lang)}</p>
            </div>
        );
    }

    return (
        <div className="h-full flex flex-col bg-surface">
            <TopBar
                title={t('tab_history', lang)}
                icon={HistoryIcon}
                actions={
                    <Button
                        variant="ghost"
                        size="icon"
                        onClick={() => {
                            const csvContent = generateCsv(sessions, exercises);
                            downloadCsv(csvContent);
                        }}
                        title={t('export_csv', lang)}
                        aria-label={t('export_csv', lang)}
                    >
                        <Download size={24} className="text-on-surface-variant hover:text-primary transition-colors" />
                    </Button>
                }
            />
            <div className="flex-1 overflow-y-auto p-4 pb-20">
                <div className="max-w-2xl mx-auto space-y-4">
                    {/* Regular Workout Sessions */}
                    {sessions.filter(s => s.type === 'STANDARD').map((session) => {
                        const totalWork = calculateSessionWork(session);

                        return (
                            <Card
                                key={session.id}
                                className="cursor-pointer hover:bg-surface-container-high transition-colors"
                                onClick={() => setEditingSession(JSON.parse(JSON.stringify(session)))}
                            >
                                <div className="flex justify-between items-start">
                                    <div className="flex-1">
                                        <div className="flex items-center gap-3 flex-wrap">
                                            <span className="font-medium text-on-surface text-lg">
                                                {new Date(session.startTime).toISOString().split('T')[0]}
                                            </span>
                                            <span className="text-sm text-on-surface-variant">
                                                {new Date(session.startTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                                            </span>
                                            {session.endTime && (
                                                <span className="text-sm text-on-surface-variant">
                                                    {formatDuration(session.startTime, session.endTime)}
                                                </span>
                                            )}
                                            <span className="text-sm text-on-surface-variant">
                                                {session.planName || t('no_plan', lang)}
                                            </span>
                                            {session.userBodyWeight && (
                                                <span className="px-2 py-0.5 rounded-full bg-surface-container-high text-on-surface text-xs">
                                                    {session.userBodyWeight}kg
                                                </span>
                                            )}
                                        </div>
                                        <div className="mt-2 text-xs text-on-surface-variant flex items-center">
                                            <span className="inline-flex items-center">
                                                {t('sets_count', lang)}: <span className="text-on-surface font-medium ml-1">{session.sets.length}</span>
                                            </span>
                                            {totalWork > 0 && (
                                                <span className="ml-4 inline-flex items-center gap-1">
                                                    <Gauge size={12} />
                                                    {(totalWork / 1000).toFixed(1)}t
                                                </span>
                                            )}
                                        </div>
                                    </div>

                                    <div className="relative">
                                        <Button
                                            onClick={(e) => {
                                                e.stopPropagation();
                                                const rect = e.currentTarget.getBoundingClientRect();
                                                setMenuState({
                                                    id: session.id,
                                                    x: rect.right + window.scrollX,
                                                    y: rect.bottom + window.scrollY
                                                });
                                            }}
                                            variant="ghost"
                                            size="icon"
                                            aria-label="Session Actions"
                                            className="text-on-surface-variant hover:text-primary"
                                        >
                                            <MoreVertical size={24} />
                                        </Button>
                                    </div>
                                </div>
                            </Card>
                        )
                    })}

                    {/* Quick Log Sessions */}
                    {sessions.filter(s => s.type === 'QUICK_LOG').length > 0 && (
                        <div className="mt-8">
                            <h3 className="text-xl font-medium text-on-surface mb-4 px-2">{t('quick_log', lang)}</h3>
                            {(Object.entries(
                                sessions
                                    .filter(s => s.type === 'QUICK_LOG')
                                    .reduce<Record<string, WorkoutSession[]>>((groups, session) => {
                                        const date = new Date(session.startTime).toISOString().split('T')[0];
                                        if (!groups[date]) groups[date] = [];
                                        groups[date].push(session);
                                        return groups;
                                    }, {})
                            ) as [string, WorkoutSession[]][])
                                .sort(([a], [b]) => b.localeCompare(a))
                                .map(([date, daySessions]) => (
                                    <div key={date} className="mb-4">
                                        <div className="text-sm text-on-surface-variant px-2 mb-2 font-medium">{date}</div>
                                        <div className="space-y-2">
                                            {daySessions
                                                .reduce<WorkoutSet[]>((acc, session) => acc.concat(session.sets), [])
                                                .map((set, idx) => (
                                                    <Card
                                                        key={set.id}
                                                        className="bg-surface-container-low flex justify-between items-center"
                                                    >
                                                        <div className="flex-1">
                                                            <div className="font-medium text-on-surface">
                                                                {set.exerciseName}
                                                                {set.side && <span className="ml-2 text-xs font-medium text-on-surface-variant">{t(set.side.toLowerCase() as any, lang)}</span>}
                                                            </div>
                                                            <div className="text-sm text-on-surface-variant mt-1">
                                                                {formatSetMetrics(set, lang)}
                                                            </div>
                                                            <div className="text-xs text-on-surface-variant mt-1">
                                                                {new Date(set.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                                                            </div>
                                                        </div>
                                                        <div className="flex gap-1">
                                                            <Button
                                                                onClick={() => {
                                                                    // Find the session this set belongs to and open edit mode
                                                                    const parentSession = daySessions.find(s => s.sets.some(st => st.id === set.id));
                                                                    if (parentSession) {
                                                                        setEditingSetInfo({ sessionId: parentSession.id, set: set });
                                                                    }
                                                                }}
                                                                variant="ghost"
                                                                size="icon"
                                                                className="text-on-surface-variant hover:text-primary"
                                                                aria-label={t('edit', lang)}
                                                            >
                                                                <Pencil size={24} />
                                                            </Button>
                                                            <Button
                                                                onClick={() => {
                                                                    // Find the session and set up for deletion
                                                                    const parentSession = daySessions.find(s => s.sets.some(st => st.id === set.id));
                                                                    if (parentSession) {
                                                                        setDeletingSetInfo({ sessionId: parentSession.id, setId: set.id });
                                                                    }
                                                                }}
                                                                variant="ghost"
                                                                size="icon"
                                                                className="text-error hover:text-error"
                                                                aria-label={t('delete', lang)}
                                                            >
                                                                <Trash2 size={24} />
                                                            </Button>
                                                        </div>
                                                    </Card>
                                                ))}
                                        </div>
                                    </div>
                                ))}
                        </div>
                    )}
                </div>
            </div>

            {/* MENU PORTAL */}
            {menuState && typeof document !== 'undefined' && createPortal(
                <>
                    <div
                        className="fixed inset-0 z-50"
                        onClick={(e) => {
                            e.stopPropagation();
                            setMenuState(null);
                        }}
                    />
                    <div
                        className="absolute bg-surface-container-high rounded-xl shadow-elevation-2 z-50 min-w-[160px] py-1 flex flex-col overflow-hidden animate-menu-enter origin-top-right"
                        style={{
                            top: menuState.y,
                            left: menuState.x,
                        }}
                    >
                        <button
                            onClick={(e) => {
                                e.stopPropagation();
                                const session = sessions.find(s => s.id === menuState.id);
                                if (session) {
                                    navigate(`/plans?createFromSessionId=${session.id}`);
                                }
                                setMenuState(null);
                            }}
                            className="w-full relative overflow-hidden text-left px-4 py-3 hover:bg-on-surface/10 text-on-surface flex items-center gap-3 transition-colors text-sm font-medium"
                        >
                            <Ripple />
                            <ClipboardList size={18} />
                            {t('create_plan', lang) || 'Create Plan'}
                        </button>
                        <button
                            onClick={(e) => {
                                e.stopPropagation();
                                const session = sessions.find(s => s.id === menuState.id);
                                if (session) {
                                    setEditingSession(JSON.parse(JSON.stringify(session)));
                                }
                                setMenuState(null);
                            }}
                            className="w-full relative overflow-hidden text-left px-4 py-3 hover:bg-on-surface/10 text-on-surface flex items-center gap-3 transition-colors text-sm font-medium"
                        >
                            <Ripple />
                            <Pencil size={18} />
                            {t('edit', lang)}
                        </button>
                        <button
                            onClick={(e) => {
                                e.stopPropagation();
                                setDeletingId(menuState.id);
                                setMenuState(null);
                            }}
                            className="w-full relative overflow-hidden text-left px-4 py-3 hover:bg-error-container/10 text-error flex items-center gap-3 transition-colors text-sm font-medium"
                        >
                            <Ripple color="rgba(242, 184, 181, 0.2)" />
                            <Trash2 size={18} />
                            {t('delete', lang)}
                        </button>
                    </div>
                </>,
                document.body
            )}

            {/* DELETE CONFIRMATION MODAL */}
            <Modal
                isOpen={!!(deletingId || deletingSetInfo)}
                onClose={() => {
                    setDeletingId(null);
                    setDeletingSetInfo(null);
                }}
                title={deletingId ? t('delete_workout', lang) : t('delete_set', lang) || 'Delete Set'}
                maxWidth="sm"
            >
                <div className="space-y-6">
                    <p className="text-sm text-on-surface-variant">
                        {deletingId ? t('delete_confirm', lang) : t('delete_set_confirm', lang) || 'Are you sure you want to delete this set?'}
                    </p>
                    <div className="flex justify-end gap-2">
                        <Button
                            onClick={() => {
                                setDeletingId(null);
                                setDeletingSetInfo(null);
                            }}
                            variant="ghost"
                            size="sm"
                        >
                            {t('cancel', lang)}
                        </Button>
                        <Button
                            onClick={handleConfirmDelete}
                            variant="destructive"
                            size="sm"
                        >
                            {t('delete', lang)}
                        </Button>
                    </div>
                </div>
            </Modal>

            {/* EDIT SESSION MODAL */}
            {editingSession && (
                <SideSheet
                    isOpen={!!editingSession}
                    onClose={() => setEditingSession(null)}
                    title={t('edit', lang)}
                    width="lg"
                    footer={
                        <div className="flex justify-end">
                            <Button onClick={handleSaveEdit}>
                                <Save size={16} className="mr-2" />
                                {t('save', lang)}
                            </Button>
                        </div>
                    }
                >
                    <div className="space-y-6">
                        {/* Meta Info */}
                        <div className="grid grid-cols-2 gap-4">
                            <FilledInput
                                label={t('start_time', lang)}
                                type="datetime-local"
                                value={formatDateForInput(editingSession.startTime)}
                                onChange={(e: any) => setEditingSession({ ...editingSession, startTime: parseDateFromInput(e.target.value) })}
                            />
                            <FilledInput
                                label={t('end_time', lang)}
                                type="datetime-local"
                                value={editingSession.endTime ? formatDateForInput(editingSession.endTime) : ''}
                                onChange={(e: any) => setEditingSession({ ...editingSession, endTime: parseDateFromInput(e.target.value) })}
                            />
                        </div>
                        <FilledInput
                            label={t('weight_kg', lang)}
                            type="number"
                            value={editingSession.userBodyWeight || ''}
                            onChange={(e: any) => setEditingSession({ ...editingSession, userBodyWeight: parseFloat(e.target.value) })}
                        />

                        <div className="space-y-3">
                            <h3 className="text-sm font-medium text-primary ml-1">{t('sets_count', lang)} ({editingSession.sets.length})</h3>
                            {editingSession.sets.map((set, idx) => (
                                <div key={set.id} className="bg-surface-container-low p-3 rounded-xl border border-outline-variant/20 flex items-center justify-between">
                                    <div className="flex-1">
                                        <div className="flex items-center gap-2 mb-1">
                                            <span className="w-5 h-5 rounded-full bg-secondary-container text-on-secondary-container text-[10px] font-bold flex items-center justify-center">{idx + 1}</span>
                                            <span className="font-medium text-on-surface text-sm">{set.exerciseName}</span>
                                            {set.side && <span className="text-xs text-on-surface-variant font-medium bg-surface-container px-1.5 py-0.5 rounded">{t(set.side.toLowerCase() as any, lang)}</span>}
                                        </div>
                                        <div className="text-sm text-on-surface-variant pl-7">
                                            {formatSetMetrics(set, lang)}
                                        </div>
                                    </div>
                                    <div className="flex gap-1">
                                        <Button
                                            onClick={() => setEditingSetInfo({ sessionId: editingSession.id, set: set })}
                                            variant="ghost"
                                            size="icon"
                                            className="text-on-surface-variant hover:text-primary"
                                            title={t('edit', lang)}
                                        >
                                            <Pencil size={18} />
                                        </Button>
                                        <Button
                                            onClick={() => handleDeleteSet(set.id)}
                                            variant="ghost"
                                            size="icon"
                                            className="text-on-surface-variant hover:text-error hover:bg-error-container/10"
                                            title={t('delete', lang)}
                                        >
                                            <Trash2 size={18} />
                                        </Button>
                                    </div>
                                </div>
                            ))}
                        </div>



                    </div>
                </SideSheet>
            )
            }
            {editingSetInfo && (
                <EditSetModal
                    isOpen={!!editingSetInfo}
                    onClose={() => setEditingSetInfo(null)}
                    set={editingSetInfo.set}
                    exerciseDef={exercises.find(e => e.id === editingSetInfo.set.exerciseId)}
                    onSave={handleSaveSetFromModal}
                    lang={lang}
                />
            )}
        </div >
    );
};

export default History;
