import React, { useCallback, useRef, useEffect, useState } from 'react';
import { useAppDispatch, useAppSelector } from '../../hooks/hooks';
import { fetchChatMessages, sendChatMessage, clearChat } from './chatSlice';
import { MessageInput } from './MessageInput';
import { MessageList } from "./MessageList";

import { authExpired } from '../auth/authSlice';
import { endChatSession } from '../../api/zozochat';

import { AgencyLogo } from '../../components/AgencyLogo/AgencyLogo';

import { ChatCloseType } from '../../types';

import styles from './ChatWindow.module.scss';

export function ChatWindow({ chatIsOpen }: { chatIsOpen: boolean; }) {
    const dispatch = useAppDispatch();
    const { verified, conversationId, conversationStatus, email } = useAppSelector((s) => s.auth);
    const { messages, chatStatus, conversationStatus: chatConversationStatus, error } = useAppSelector((s) => s.chat);
    const isLoading = chatStatus === 'loading';

    const [confirmCloseOpen, setConfirmCloseOpen] = useState(false);
    const [confirmLogoutOpen, setConfirmLogoutOpen] = useState(false);

    const [systemCloseOpen, setSystemCloseOpen] = useState(false);
    const [systemMessage, setSystemMessage] = useState<string | null>(null);

    const scrollRef = useRef<HTMLDivElement | null>(null);

    const sessionRestoreRequestedRef = useRef(false);
    const endingRef = useRef(false); // for when user clicks "End chat"
    const closedHandledRef = useRef(false); // for when the chat is closed by the system, e.g. agent ends it

    const sessionTtlSeconds = useAppSelector(s => s.auth.sessionTtlSeconds);
    const GRACE_SECONDS = 2 * 60;
    // total TTL from backend (default 10 min)
    const TOTAL_TTL_SECONDS = sessionTtlSeconds ?? 10 * 60;
    // visible countdown seconds (after grace)
    const COUNTDOWN_SECONDS = Math.max(0, TOTAL_TTL_SECONDS - GRACE_SECONDS);

    // Track last user activity (timestamp)
    const lastActivityAtRef = useRef<number>(Date.now());
    const markActivity = useCallback(() => {
        lastActivityAtRef.current = Date.now();
    }, []);
    const [idleSeconds, setIdleSeconds] = useState(0);
    const formatMMSS = (s: number) =>
        `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;

    useEffect(() => {
        const id = window.setInterval(() => {
            const idle = Math.floor((Date.now() - lastActivityAtRef.current) / 1000);
            setIdleSeconds(idle);
        }, 1000);

        return () => window.clearInterval(id);
    }, []);
    const afterGrace = idleSeconds >= GRACE_SECONDS;
    const countdownRemaining = afterGrace
        ? Math.max(0, COUNTDOWN_SECONDS - (idleSeconds - GRACE_SECONDS))
        : null;


    // Fetch chat history once the session is restored
    useEffect(() => {
        if (!conversationId || !verified) return;

        // stop fetching if chat is closed
        if (chatConversationStatus === 'closed') return;


        // Otherwise, fetch via REST
        dispatch(fetchChatMessages());

    }, [
        conversationId,
        verified,
        chatConversationStatus,
        dispatch
    ]);


    // Reset the popup + close guard when a new session starts
    useEffect(() => {
        // when a new conversation starts, clear old terminal UI state
        closedHandledRef.current = false;
        setSystemCloseOpen(false);
        setSystemMessage(null);
    }, [conversationId]);

    // reset when you become verified again (safe)
    useEffect(() => {
        if (!verified) return;

        closedHandledRef.current = false;
        setSystemCloseOpen(false);
        setSystemMessage(null);
    }, [verified]);


    // auto-scroll when messages change
    useEffect(() => {
        const el = scrollRef.current;
        if (!el) return;
        el.scrollTop = el.scrollHeight;
    }, [messages]);

    const sendViaRest = useCallback(
        async (text: string) => {
            if (!email || !conversationId) return;

            // If your thunk needs more fields, pass them here (content/message/etc).
            const res = await dispatch(
                sendChatMessage({ email, conversationId, content: text })
            );

            // If REST send succeeded, refresh messages (simple and reliable)
            if (sendChatMessage.fulfilled.match(res)) {
                dispatch(fetchChatMessages());
            }
        },
        [dispatch, email, conversationId]
    );

    const onSend = useCallback(
        async (text: string) => {

            // When user sends a message, reset the inactivity timer (indicates activity in the chat)
            //resetInactivityTimer();
            markActivity();

            // FREE: always REST
            if (!false) {
                await sendViaRest(text);
                return;
            }

        },
        [sendViaRest,
            markActivity,
        ]
    );

    useEffect(() => {
        const serverClosed = chatConversationStatus === 'closed';
        const sessionExpired = chatStatus === 'failed' && error === 'Session expired';
        if (!serverClosed && !sessionExpired) return;
        if (closedHandledRef.current) return;

        closedHandledRef.current = true;


        setSystemMessage(
            serverClosed
                ? 'The agent has closed the chat.'
                : 'Your session expired. The chat was closed by the system.'
        );
        setSystemCloseOpen(true);
    }, [
        chatConversationStatus,
        chatStatus,
        error,
    ]);

    useEffect(() => {
        if (!afterGrace) return;
        if (countdownRemaining !== 0) return;
        if (closedHandledRef.current) return;

        closedHandledRef.current = true;


        handleAction('logout');
    }, [
        afterGrace,
        countdownRemaining,
    ]);

    const handleAction = useCallback(async (type: ChatCloseType) => {
        if (endingRef.current) return;
        endingRef.current = true;

        try {
            // Send the type ('logout' or 'endChat') to the server
            await endChatSession({ action: type });
        } catch (e) {
            console.error(`Action ${type} failed:`, e);
        } finally {
            // Local Cleanup (Always run)

            closedHandledRef.current = false;
            dispatch(clearChat());
            dispatch(authExpired());

            endingRef.current = false;
        }
    }, [
        dispatch, endChatSession]);


    const renderStatusBar = () => {
        console.log('############# conversationStatus ###########', { conversationStatus });
        if (!verified) return null;

        // Priority 1: Loading state (Standard/Free mode needs this most)
        if (chatStatus === 'loading') {
            return <div className={styles.status}>Loading...</div>;
        }
        // Priority 2: Connection status (PRO feature)
        if (false) {
        } else {

            // Priority 3: Waiting for Agent (Common to both)
            if (chatConversationStatus === "pending_approval") {
                return (
                    <div className={styles.pendingBanner}>
                        Waiting for an agent...
                    </div>
                );
            }
        }

        return null;
    };

    if (!verified) return <div>Please verify your email first.</div>;

    return (
        <div className={styles.zozoChatGlobalClass}>
            {chatConversationStatus !== 'closed' &&
                !systemCloseOpen &&
                countdownRemaining != null &&
                countdownRemaining > 0 && (
                    <div className={styles.sessionWarning}>
                        Due to inactivity, the chat will close in {formatMMSS(countdownRemaining)}.
                    </div>
                )}
            {chatConversationStatus !== "closed" &&
                <div className={styles.chatheader}>
                    {renderStatusBar()}

                    {!isLoading && error && <div className={styles.error}>{error}</div>}
                    <div className={styles.buttons}>
                        <button type="button" onClick={() => setConfirmCloseOpen(true)}>End chat</button>
                        <button type="button" onClick={() => setConfirmLogoutOpen(true)}>Logout</button>
                    </div>
                </div>
            }

            {
                confirmCloseOpen && (
                    <div className={styles.chatConfirmOverlay} data-test="confirm-close">
                        <div className={styles.chatConfirmBox}>
                            <p>Are you sure you want to close the chat?</p>

                            <div className={styles.actions}>
                                <button
                                    data-test="confirm-close-yes"
                                    onClick={async () => {
                                        setConfirmCloseOpen(false);
                                        await handleAction('endChat');
                                    }}
                                >
                                    Yes
                                </button>

                                <button
                                    data-test="confirm-close-no"
                                    onClick={() => setConfirmCloseOpen(false)}
                                >
                                    No
                                </button>
                            </div>
                        </div>
                    </div>
                )
            }

            {
                confirmLogoutOpen && (
                    <div className={styles.chatConfirmOverlay} data-test="confirm-logout">
                        <div className={styles.chatConfirmBox}>
                            <p>Are you sure you want to logout?<br />
                                You can return to the chat at any time in the next 30 days.<br />
                                After 30 days it will be closed automatically.</p>

                            <div className={styles.actions}>
                                <button
                                    data-test="confirm-logout-yes"
                                    onClick={async () => {
                                        setConfirmLogoutOpen(false);
                                        await handleAction('logout');
                                    }}
                                >
                                    Yes
                                </button>

                                <button
                                    data-test="confirm-logout-no"
                                    onClick={() => setConfirmLogoutOpen(false)}
                                >
                                    No
                                </button>
                            </div>
                        </div>
                    </div>
                )
            }

            {
                systemCloseOpen && (
                    <div className={styles.chatConfirmOverlay} data-test="system-close">
                        <div className={styles.chatConfirmBox}>
                            <p>{systemMessage}</p>

                            <div className={styles.actions}>
                                <button
                                    data-test="system-close-ok"
                                    onClick={() => {
                                        setSystemCloseOpen(false);
                                        handleAction('logout');
                                    }}
                                >
                                    Close chat
                                </button>
                            </div>
                        </div>
                    </div>
                )
            }

            <div className={styles.messages} ref={scrollRef}>
                <MessageList
                    messages={messages}
                />
            </div>


            {chatConversationStatus !== "closed" &&
                <>
                    <MessageInput
                        onSend={onSend}
                        disabled={!verified || !conversationId || systemCloseOpen}
                    />
                    <button
                        type="button"
                        className={styles.refreshBtn}
                        onClick={() => email && conversationId && dispatch(fetchChatMessages())}
                        disabled={isLoading}
                    >
                        Refresh
                    </button>
                </>
            }

            <AgencyLogo className={styles.agencyLogoAfterValidation} />
        </div >
    );
}
