import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Button, Group, Modal, Stack, Text, ThemeIcon } from '@mantine/core';
import { IconCheck, IconClockExclamation } from '@tabler/icons-react';
import { jwtDecode } from 'jwt-decode';
import { showNotification } from '@mantine/notifications';
import { __, sprintf } from '@wordpress/i18n';
import { onSignOutSuccess, refreshSessionToken } from '../../store/auth/sessionSlice';

// Warn this long before the JWT expires
const WARN_BEFORE_MS = 10 * 60 * 1000;

const SessionExpiryModal = () => {
    const dispatch = useDispatch();
    const { token, signedIn } = useSelector((state) => state.auth.session);
    const [now, setNow] = useState(() => Date.now());
    const [refreshing, setRefreshing] = useState(false);
    const [dismissed, setDismissed] = useState(false);

    const tokenExp = useMemo(() => {
        if (!token) return null;
        try {
            const decoded = jwtDecode(token);
            return decoded?.exp ? decoded.exp * 1000 : null;
        } catch (e) {
            return null;
        }
    }, [token]);

    // A new token (login or successful refresh) re-arms the warning
    useEffect(() => {
        setDismissed(false);
    }, [token]);

    const remaining = tokenExp !== null ? tokenExp - now : null;
    const inWarningWindow = signedIn && remaining !== null && remaining > 0 && remaining <= WARN_BEFORE_MS;

    // Recompute from Date.now() on an interval + on window focus — background
    // tabs throttle timers, so a decrementing countdown would drift. The
    // interval tightens to 1s only while the countdown is visible.
    useEffect(() => {
        if (!signedIn || tokenExp === null) return undefined;
        const tick = () => setNow(Date.now());
        const id = setInterval(tick, inWarningWindow ? 1000 : 30000);
        window.addEventListener('focus', tick);
        return () => {
            clearInterval(id);
            window.removeEventListener('focus', tick);
        };
    }, [signedIn, tokenExp, inWarningWindow]);

    const handleLogout = useCallback(() => {
        // Same client-side sign-out path BaseService's interceptor uses on an
        // expired token. Deliberately NOT calling POST /logout — that endpoint
        // deletes the user's FCM token and would kill their mobile push.
        dispatch(onSignOutSuccess());
        window.location = `${appLocalizer?.homeUrl}/lazytasks/#/lazy-login`;
    }, [dispatch]);

    // Hard deadline: the token is expired — force logout even if the warning was dismissed
    useEffect(() => {
        if (signedIn && remaining !== null && remaining <= 0) {
            handleLogout();
        }
    }, [signedIn, remaining, handleLogout]);

    const handleStayLoggedIn = () => {
        setRefreshing(true);
        dispatch(refreshSessionToken())
            .unwrap()
            .then(() => {
                // Modal closes by itself: the fresh token moves tokenExp out of the warning window
                showNotification({
                    color: 'green',
                    title: __('Success', 'lazytasks-project-task-management'),
                    message: __('Your session has been extended.', 'lazytasks-project-task-management'),
                    icon: <IconCheck size={16} />,
                    autoClose: 3000,
                });
            })
            .catch(() => {
                showNotification({
                    color: 'red',
                    title: __('Error', 'lazytasks-project-task-management'),
                    message: __('Could not extend your session. Please save your work and log in again.', 'lazytasks-project-task-management'),
                    autoClose: 4000,
                });
            })
            .finally(() => setRefreshing(false));
    };

    const minutes = remaining > 0 ? Math.floor(remaining / 60000) : 0;
    const seconds = remaining > 0 ? Math.floor((remaining % 60000) / 1000) : 0;
    const countdown = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;

    return (
        <Modal
            opened={inWarningWindow && !dismissed}
            onClose={() => setDismissed(true)}
            centered
            zIndex={10001}
            closeOnClickOutside={false}
            title={
                <Group gap={8}>
                    <ThemeIcon color="orange" variant="light" radius="xl" size="md">
                        <IconClockExclamation size={18} stroke={1.5} />
                    </ThemeIcon>
                    <Text fw={700} size="sm">{__('Session expiring soon', 'lazytasks-project-task-management')}</Text>
                </Group>
            }
        >
            <Stack gap="md">
                <Text size="sm">
                    {sprintf(
                        /* translators: %s: remaining time as mm:ss countdown */
                        __('Your session will expire in %s. You will be logged out automatically unless you extend it.', 'lazytasks-project-task-management'),
                        countdown
                    )}
                </Text>
                <Group justify="flex-end" gap="xs">
                    <Button variant="default" color="gray" onClick={handleLogout} disabled={refreshing}>
                        {__('Logout now', 'lazytasks-project-task-management')}
                    </Button>
                    <Button color="#39758D" onClick={handleStayLoggedIn} loading={refreshing}>
                        {__('Stay logged in', 'lazytasks-project-task-management')}
                    </Button>
                </Group>
            </Stack>
        </Modal>
    );
};

export default SessionExpiryModal;
