import React, { useState, useEffect, useCallback, useRef } from 'react';
import { useQuery, useConvex } from 'convex/react';
import { api } from '../../../../convex/_generated/api';
import Sidebar from '../components/Sidebar';
import ChatArea from '../components/ChatArea';
import VoiceStage from '../components/VoiceStage';
import { useVoice } from '../contexts/VoiceContext';
import FriendsView from '../components/FriendsView';
import MembersList from '../components/MembersList';
import ChatHeader from '../components/ChatHeader';
import { useToasts } from '../components/Toast';
import { PresenceProvider } from '../contexts/PresenceContext';

const Chat = () => {
    const [view, setView] = useState('server');
    const [activeChannel, setActiveChannel] = useState(null);
    const [username, setUsername] = useState('');
    const [userId, setUserId] = useState(null);
    const [channelKeys, setChannelKeys] = useState({});
    const [activeDMChannel, setActiveDMChannel] = useState(null);
    const [showMembers, setShowMembers] = useState(true);
    const [showPinned, setShowPinned] = useState(false);

    const convex = useConvex();
    const { toasts, addToast, removeToast, ToastContainer } = useToasts();
    const prevDmChannelsRef = useRef(null);
    const { toggleMute } = useVoice();

    // Keyboard shortcuts
    useEffect(() => {
        const handler = (e) => {
            if (e.ctrlKey && e.key === 'k') {
                e.preventDefault();
                // Quick switcher placeholder - could open a search modal
            }
            if (e.ctrlKey && e.shiftKey && e.key === 'M') {
                e.preventDefault();
                toggleMute();
            }
        };
        window.addEventListener('keydown', handler);
        return () => window.removeEventListener('keydown', handler);
    }, [toggleMute]);

    const channels = useQuery(api.channels.list) || [];

    const rawChannelKeys = useQuery(
        api.channelKeys.getKeysForUser,
        userId ? { userId } : "skip"
    );

    const dmChannels = useQuery(
        api.dms.listDMs,
        userId ? { userId } : "skip"
    ) || [];

    useEffect(() => {
        const storedUsername = localStorage.getItem('username');
        const storedUserId = localStorage.getItem('userId');
        if (storedUsername) setUsername(storedUsername);
        if (storedUserId) setUserId(storedUserId);
    }, []);

    useEffect(() => {
        if (!rawChannelKeys || rawChannelKeys.length === 0) return;
        const privateKey = sessionStorage.getItem('privateKey');
        if (!privateKey) return;

        async function decryptKeys() {
            const keys = {};
            for (const item of rawChannelKeys) {
                try {
                    const bundleJson = await window.cryptoAPI.privateDecrypt(privateKey, item.encrypted_key_bundle);
                    Object.assign(keys, JSON.parse(bundleJson));
                } catch (e) {
                    console.error(`Failed to decrypt keys for channel ${item.channel_id}`, e);
                }
            }
            setChannelKeys(keys);
        }

        decryptKeys();
    }, [rawChannelKeys]);

    useEffect(() => {
        if (activeChannel || channels.length === 0) return;
        const firstTextChannel = channels.find(c => c.type === 'text');
        if (firstTextChannel) {
            setActiveChannel(firstTextChannel._id);
        }
    }, [channels, activeChannel]);

    const openDM = useCallback(async (targetUserId, targetUsername) => {
        const uid = localStorage.getItem('userId');
        if (!uid) return;

        try {
            const { channelId, created } = await convex.mutation(api.dms.openDM, {
                userId: uid,
                targetUserId
            });

            if (created) {
                const keyBytes = new Uint8Array(32);
                crypto.getRandomValues(keyBytes);
                const keyHex = Array.from(keyBytes).map(b => b.toString(16).padStart(2, '0')).join('');

                const allUsers = await convex.query(api.auth.getPublicKeys, {});
                const participants = allUsers.filter(u => u.id === uid || u.id === targetUserId);

                const batchKeys = [];
                for (const u of participants) {
                    if (!u.public_identity_key) continue;
                    try {
                        const payload = JSON.stringify({ [channelId]: keyHex });
                        const encryptedKeyHex = await window.cryptoAPI.publicEncrypt(u.public_identity_key, payload);
                        batchKeys.push({
                            channelId,
                            userId: u.id,
                            encryptedKeyBundle: encryptedKeyHex,
                            keyVersion: 1
                        });
                    } catch (e) {
                        console.error('Failed to encrypt DM key for user', u.id, e);
                    }
                }

                if (batchKeys.length > 0) {
                    await convex.mutation(api.channelKeys.uploadKeys, { keys: batchKeys });
                }
            }

            setActiveDMChannel({ channel_id: channelId, other_username: targetUsername });
            setView('me');

        } catch (err) {
            console.error('Error opening DM:', err);
        }
    }, [convex]);

    const handleSelectChannel = useCallback((channelId) => {
        setActiveChannel(channelId);
        setShowPinned(false);
    }, []);

    const activeChannelObj = channels.find(c => c._id === activeChannel);
    const { room, voiceStates } = useVoice();

    const isDMView = view === 'me' && activeDMChannel;
    const isServerTextChannel = view === 'server' && activeChannel && activeChannelObj?.type !== 'voice';
    const currentChannelId = isDMView ? activeDMChannel.channel_id : activeChannel;

    function renderMainContent() {
        if (view === 'me') {
            if (activeDMChannel) {
                return (
                    <div className="chat-container">
                        <ChatHeader
                            channelName={activeDMChannel.other_username}
                            channelType="dm"
                            onToggleMembers={() => {}}
                            showMembers={false}
                            onTogglePinned={() => setShowPinned(p => !p)}
                        />
                        <div className="chat-content">
                            <ChatArea
                                channelId={activeDMChannel.channel_id}
                                channelName={activeDMChannel.other_username}
                                channelType="dm"
                                channelKey={channelKeys[activeDMChannel.channel_id]}
                                username={username}
                                userId={userId}
                                showMembers={false}
                                onToggleMembers={() => {}}
                                onOpenDM={openDM}
                                showPinned={showPinned}
                                onTogglePinned={() => setShowPinned(false)}
                            />
                        </div>
                    </div>
                );
            }
            return <FriendsView onOpenDM={openDM} />;
        }

        if (activeChannel) {
            if (activeChannelObj?.type === 'voice') {
                return <VoiceStage room={room} channelId={activeChannel} voiceStates={voiceStates} channelName={activeChannelObj?.name} />;
            }
            return (
                <div className="chat-container">
                    <ChatHeader
                        channelName={activeChannelObj?.name || activeChannel}
                        channelType="text"
                        channelTopic={activeChannelObj?.topic}
                        onToggleMembers={() => setShowMembers(!showMembers)}
                        showMembers={showMembers}
                        onTogglePinned={() => setShowPinned(p => !p)}
                        serverName="Secure Chat"
                    />
                    <div className="chat-content">
                        <ChatArea
                            channelId={activeChannel}
                            channelName={activeChannelObj?.name || activeChannel}
                            channelType="text"
                            channelKey={channelKeys[activeChannel]}
                            username={username}
                            userId={userId}
                            showMembers={showMembers}
                            onToggleMembers={() => setShowMembers(!showMembers)}
                            onOpenDM={openDM}
                            showPinned={showPinned}
                            onTogglePinned={() => setShowPinned(false)}
                        />
                        <MembersList
                            channelId={activeChannel}
                            visible={showMembers}
                            onMemberClick={(member) => {}}
                        />
                    </div>
                </div>
            );
        }

        return (
            <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#b9bbbe', flexDirection: 'column' }}>
                <h2>Welcome to Secure Chat</h2>
                <p>No channels found.</p>
                <p>Click the <b>+</b> in the sidebar to create your first encrypted channel.</p>
            </div>
        );
    }

    if (!userId) {
        return (
            <div className="app-container">
                <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#b9bbbe' }}>
                    Loading...
                </div>
            </div>
        );
    }

    return (
        <PresenceProvider userId={userId}>
            <div className="app-container">
                <Sidebar
                    channels={channels}
                    activeChannel={activeChannel}
                    onSelectChannel={handleSelectChannel}
                    username={username}
                    channelKeys={channelKeys}
                    view={view}
                    onViewChange={setView}
                    onOpenDM={openDM}
                    activeDMChannel={activeDMChannel}
                    setActiveDMChannel={setActiveDMChannel}
                    dmChannels={dmChannels}
                    userId={userId}
                />
                {renderMainContent()}
                <ToastContainer />
            </div>
        </PresenceProvider>
    );
};

export default Chat;
