import VrApp from '../../vrApp';
import React, {useEffect, useRef, useState} from "react";
import {Affix, Burger, Group, Menu, Alert, Button, Text} from "@mantine/core";
import VrTemplate from "../vrTemplate";
import {IconStar, IconInfoCircle, IconMessageCircle} from "@tabler/icons-react";
import VrMenuItem from "../components/vrMenuItem";
import CreateDiagramModal from "./createDiagramModal";
import ManageDiagramsModal from "./manageDiagramsModal";
import {useNavigate, useParams} from "react-router-dom";
import {useDisclosure} from "@mantine/hooks";
import ConfigModal from "./configModal";
import log from "loglevel";
import {useFeatureState, useUserTier} from "../hooks/useFeatures";
import {useAuth0} from "@auth0/auth0-react";
import {GUEST_MODE_BANNER} from "../../content/upgradeCopy";
import {exportDiagramAsJSON, DiagramExport} from "../../util/functions/exportDiagramAsJSON";
import {isMobileVRDevice} from "../../util/deviceDetection";
import {DefaultScene} from "../../defaultScene";
import VREntryPrompt from "../components/VREntryPrompt";
import ComingSoonBadge from "../components/ComingSoonBadge";
import UpgradeBadge from "../components/UpgradeBadge";
import ChatPanel from "../components/ChatPanel";
import {getDbType} from "../../util/functions/getPath";
import PouchDB from 'pouchdb';
import {v4} from "uuid";

let vrApp: VrApp = null;

const defaultCreate = window.localStorage.getItem('createOpened') === 'true';
const defaultConfig = window.localStorage.getItem('configOpened') === 'true';
const defaultManage = window.localStorage.getItem('manageOpened') === 'true';
const defaultMenuOpened = window.localStorage.getItem('menuOpened') !== 'false'; // Default to true (open)

export default function VrExperience() {
    const logger = log.getLogger('vrExperience');
    const params = useParams();
    const { isAuthenticated, loginWithRedirect } = useAuth0();
    const [guestBannerDismissed, setGuestBannerDismissed] = useState(false);
    const [menuOpened, setMenuOpened] = useState(defaultMenuOpened);

    // Feature flags - get states instead of just enabled boolean
    const createDiagramState = useFeatureState('createDiagram');
    const createFromTemplateState = useFeatureState('createFromTemplate');
    const manageDiagramsState = useFeatureState('manageDiagrams');
    const shareCollaborateState = useFeatureState('shareCollaborate');
    console.log('[Share] shareCollaborateState:', shareCollaborateState);
    const editDataState = useFeatureState('editData');
    const configState = useFeatureState('config');
    const enterImmersiveState = useFeatureState('enterImmersive');
    const launchMetaQuestState = useFeatureState('launchMetaQuest');
    const userTier = useUserTier();

    // Helper to check if feature should be shown (not 'off')
    const shouldShow = (state) => state !== 'off';
    const isEnabled = (state) => state === 'on';

    // Get the appropriate click handler based on feature state
    const getClickHandler = (state, enabledHandler) => {
        if (state === 'on') {
            return enabledHandler; // Feature is enabled, use the normal handler
        }
        if (state === 'basic') {
            return handleSignUp; // Feature requires sign up, trigger auth
        }
        // For 'coming-soon', 'pro', or other states, no click handler
        return null;
    };

    const handleSignUp = () => {
        loginWithRedirect({
            appState: { returnTo: window.location.pathname }
        });
    };

    const handleExportJSON = async () => {
        try {
            await exportDiagramAsJSON(dbName);
            logger.info('Diagram exported successfully');
        } catch (error) {
            logger.error('Failed to export diagram:', error);
        }
    };

    const saveState = (key, value) => {
        logger.debug('saving', key, value)
        window.localStorage.setItem(key, value ? 'true' : 'false');
    }

    const toggleMenu = () => {
        const newState = !menuOpened;
        setMenuOpened(newState);
        window.localStorage.setItem('menuOpened', newState ? 'true' : 'false');
    };
    const [createOpened, {open: openCreate, close: closeCreate}] =
        useDisclosure(defaultCreate,
            {
                onOpen: () => {
                    saveState('createOpened', true)
                }, onClose: () => {
                    saveState('createOpened', false)
                }
            });
    const [manageOpened, {open: openManage, close: closeManage}] = useDisclosure(
        defaultManage,
        {
            onOpen: () => {
                saveState('manageOpened', true)
            }, onClose: () => {
                saveState('manageOpened', false)
            }
        })
    const [configOpened, {open: openConfig, close: closeConfig}] =
        useDisclosure(
            defaultConfig,
            {
                onOpen: () => {
                    saveState('configOpened', true)
                }, onClose: () => {
                    saveState('configOpened', false)
                }
            })

    const [rerender, setRerender] = useState(0);
    const [dbName, setDbName] = useState(params.db);
    const [showVRPrompt, setShowVRPrompt] = useState(false);
    const [chatOpen, setChatOpen] = useState(!isMobileVRDevice()); // Show chat by default on desktop
    const fileInputRef = useRef<HTMLInputElement>(null);

    // Import entities from JSON file
    const handleImportClick = () => {
        fileInputRef.current?.click();
    };

    const handleFileImport = async (event: React.ChangeEvent<HTMLInputElement>) => {
        const file = event.target.files?.[0];
        if (!file) return;

        try {
            const text = await file.text();
            const data: DiagramExport = JSON.parse(text);

            if (!data.entities || !Array.isArray(data.entities)) {
                throw new Error('Invalid file format: missing entities array');
            }

            logger.info(`Importing ${data.entities.length} entities from ${file.name}`);

            let importedCount = 0;
            let connectionCount = 0;

            // First pass: import non-connection entities
            for (const entity of data.entities) {
                if (entity.template === '#connection-template') {
                    continue; // Handle connections in second pass
                }

                // Generate new ID to avoid conflicts and ensure required fields
                const newEntity = {
                    ...entity,
                    id: entity._id || entity.id || v4(),
                    type: entity.type || 'entity',
                };

                // Remove PouchDB fields
                delete newEntity._id;
                delete newEntity._rev;

                const createEvent = new CustomEvent('chatCreateEntity', {
                    detail: {entity: newEntity},
                    bubbles: true
                });
                document.dispatchEvent(createEvent);
                importedCount++;
            }

            // Second pass: import connections
            for (const entity of data.entities) {
                if (entity.template !== '#connection-template') {
                    continue;
                }

                const newEntity = {
                    ...entity,
                    id: entity._id || entity.id || v4(),
                    type: entity.type || 'entity',
                };

                delete newEntity._id;
                delete newEntity._rev;

                const connEvent = new CustomEvent('chatCreateEntity', {
                    detail: {entity: newEntity},
                    bubbles: true
                });
                document.dispatchEvent(connEvent);
                connectionCount++;
            }

            logger.info(`Import complete: ${importedCount} entities, ${connectionCount} connections`);
            alert(`Imported ${importedCount} entities and ${connectionCount} connections from "${data.name || file.name}".`);

        } catch (err) {
            logger.error('Failed to import file:', err);
            alert(`Failed to import file: ${err instanceof Error ? err.message : 'Unknown error'}`);
        }

        // Reset file input so same file can be selected again
        event.target.value = '';
    };

    // Handle share based on current database type:
    // - Public: copy current URL to clipboard
    // - Local: create one-time copy to public, share new URL
    // - Private: show "not yet supported" message
    const handleShare = async () => {
        const dbType = getDbType();
        logger.info(`[Share] Sharing diagram - type: ${dbType}, dbName: ${dbName}`);

        if (dbType === 'private') {
            alert('Sharing private diagrams is not yet supported.\n\nPrivate diagram sharing with access control is coming soon!');
            return;
        }

        if (dbType === 'local') {
            // Create a one-time copy to public
            logger.info('[Share] Creating public copy of local diagram...');

            try {
                // Generate new ID for the public copy
                const publicDbName = 'diagram-' + v4();
                const localDb = new PouchDB(dbName);
                const remoteUrl = `${window.location.origin}/pouchdb/public-${publicDbName}`;
                const remoteDb = new PouchDB(remoteUrl);

                // Get all docs from local database
                const allDocs = await localDb.allDocs({ include_docs: true });
                logger.debug(`[Share] Found ${allDocs.rows.length} documents to copy`);

                // Copy each document to the remote database
                for (const row of allDocs.rows) {
                    if (row.doc) {
                        // Remove PouchDB internal fields for clean insert
                        const { _rev, ...docWithoutRev } = row.doc as any;
                        try {
                            await remoteDb.put(docWithoutRev);
                        } catch (err) {
                            logger.warn(`[Share] Failed to copy doc ${row.id}:`, err);
                        }
                    }
                }

                const publicUrl = `${window.location.origin}/db/public/${publicDbName}`;
                logger.info(`[Share] Public copy created at: ${publicUrl}`);

                // Copy URL to clipboard
                let copied = false;
                try {
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        await navigator.clipboard.writeText(publicUrl);
                        copied = true;
                    }
                } catch (clipboardError) {
                    logger.warn('Clipboard API failed:', clipboardError);
                }

                if (copied) {
                    alert(`Public copy created!\n\nURL copied to clipboard:\n${publicUrl}\n\nNote: Your local diagram remains unchanged. The public copy will diverge independently.`);
                } else {
                    prompt('Public copy created! Share URL (copy manually):', publicUrl);
                }
            } catch (err) {
                logger.error('[Share] Failed to create public copy:', err);
                alert('Failed to create public copy. Please try again.');
            }
            return;
        }

        // Public diagram - just copy current URL
        const shareUrl = window.location.href;
        logger.info(`[Share] Sharing public URL: ${shareUrl}`);

        // Try to copy URL to clipboard with fallback
        let copied = false;
        try {
            if (navigator.clipboard && navigator.clipboard.writeText) {
                await navigator.clipboard.writeText(shareUrl);
                copied = true;
            }
        } catch (clipboardError) {
            logger.warn('Clipboard API failed:', clipboardError);
        }

        if (copied) {
            alert(`URL copied to clipboard!\n\n${shareUrl}`);
        } else {
            // Fallback: show URL in prompt so user can copy manually
            prompt('Share URL (copy manually):', shareUrl);
        }
    };

    useEffect(() => {
        const canvas = document.getElementById('vrCanvas');
        if (!canvas) {
            logger.error('no canvas');
            return;
        }
        if (vrApp) {
            logger.debug('destroying vrApp');
            vrApp.dispose();
        }
        console.log('[Share] Initializing VrApp with dbName:', dbName);
        vrApp = new VrApp(canvas as HTMLCanvasElement, dbName);
        closeManage();

        // Show VR entry prompt for all Quest users navigating to any /db/** path
        const isQuest = isMobileVRDevice();
        logger.info(`Device check: isMobileVRDevice=${isQuest}, userAgent=${navigator.userAgent}`);

        if (isQuest) {
            logger.info('Quest device detected, will show VR prompt when ready');

            // Wait for XR to be ready, then show the prompt
            let attempts = 0;
            const maxAttempts = 50;

            const waitForXRReady = setInterval(() => {
                attempts++;
                const scene = DefaultScene.Scene;
                const groundMesh = scene?.getMeshByName('ground');

                logger.debug(`XR readiness check attempt ${attempts}: scene=${!!scene}, groundMesh=${!!groundMesh}`);

                if (groundMesh || attempts >= maxAttempts) {
                    clearInterval(waitForXRReady);
                    if (groundMesh) {
                        logger.info('XR ready, showing VR entry prompt');
                        setShowVRPrompt(true);
                        logger.info(`showVRPrompt state set to true`);
                    } else {
                        logger.warn('XR setup timeout, cannot show VR prompt');
                    }
                }
            }, 500);
        }
    }, [dbName]);

    const [immersiveDisabled, setImmersiveDisabled] = useState(true);
    const navigate = useNavigate();

    // Get the appropriate indicator for a feature based on its state
    const getFeatureIndicator = (featureState) => {
        // 'off' - don't show at all (handled by shouldShow)
        // 'on' - no badge needed, feature is fully accessible
        // 'coming-soon' - show Coming Soon badge (visible to all)
        // 'basic' - show Sign Up badge (requires basic tier) - clickable to sign up
        // 'pro' - show Upgrade to Pro badge (requires pro tier)

        if (featureState === 'coming-soon') {
            return <ComingSoonBadge size="xs" />;
        }

        if (featureState === 'basic') {
            return <UpgradeBadge size="xs" tier="basic" onClick={handleSignUp} />;
        }

        if (featureState === 'pro') {
            return <UpgradeBadge size="xs" tier="pro" />;
        }

        // 'on' state - no indicator needed
        return null;
    }

    const enterImmersive = (e) => {
        logger.info('entering immersive mode');
        e.preventDefault();
        const event = new CustomEvent('enterXr', {bubbles: true});
        window.dispatchEvent(event);
    }
    const createModal = () => {
        if (createOpened) {
            return <CreateDiagramModal createOpened={createOpened} closeCreate={closeCreate}/>
        } else {
            return <></>
        }
    }
    const manageModal = () => {
        if (manageOpened) {
            return <ManageDiagramsModal openCreate={openCreate}
                                        manageOpened={manageOpened}
                                        closeManage={closeManage}
            />
        } else {
            return <></>
        }
    }

    return (
        <React.StrictMode>
        <VrTemplate>
            {/* Guest Mode Banner - Non-aggressive, dismissible (hidden for demo) */}
            {!isAuthenticated && !guestBannerDismissed && dbName !== 'demo' && (
                <Affix position={{top: 20, right: 20}} style={{maxWidth: 400}} zIndex={100}>
                    <Alert
                        variant="light"
                        color="blue"
                        title={GUEST_MODE_BANNER.title}
                        icon={<IconInfoCircle size={20} />}
                        withCloseButton
                        onClose={() => setGuestBannerDismissed(true)}
                    >
                        <Text size="sm" mb="xs">
                            {GUEST_MODE_BANNER.message}
                        </Text>
                        <Button
                            size="xs"
                            onClick={handleSignUp}
                            variant="light"
                        >
                            {GUEST_MODE_BANNER.ctaText}
                        </Button>
                    </Alert>
                </Affix>
            )}

            <ConfigModal closeConfig={closeConfig} configOpened={configOpened}/>
            {createModal()}
            {manageModal()}
            <Affix position={{top: 30, left: 60}} zIndex={100}>
                <Menu opened={menuOpened} onChange={setMenuOpened} position="bottom-start" zIndex={100}>
                    <Menu.Target>
                        <Burger opened={menuOpened} onClick={toggleMenu} size="xl"/>
                    </Menu.Target>
                    <Menu.Dropdown>
                        {/* Home is always visible */}
                        <VrMenuItem
                            tip={"Exit modeling environment and go back to main site"}
                            onClick={() => {
                                navigate("/")
                            }}
                            label="Home"
                            availableIcon={null}/>

                        {shouldShow(enterImmersiveState) && (
                            <VrMenuItem
                                tip={immersiveDisabled ? "Browser does not support WebXR. Immersive experience best viewed with Meta Quest headset" : "Enter Immersive Mode"}
                                onClick={getClickHandler(enterImmersiveState, enterImmersive)}
                                label="Enter Immersive Mode"
                                availableIcon={getFeatureIndicator(enterImmersiveState)}/>
                        )}

                        {shouldShow(launchMetaQuestState) && (
                            <VrMenuItem
                                tip="Open a new window and automatically send experience to your Meta Quest headset"
                                onClick={getClickHandler(launchMetaQuestState, () => {
                                    window.open('https://www.oculus.com/open_url/?url=' + window.location.href, 'launchQuest', 'popup')
                                })}
                                label="Launch On Meta Quest"
                                availableIcon={getFeatureIndicator(launchMetaQuestState)}/>
                        )}

                        {shouldShow(editDataState) && (
                            <>
                                <Menu.Divider/>
                                <VrMenuItem
                                    tip="Edit data on desktop (Best for large amounts of text or images).  After adding data, you can enter immersive mode to further refine the model."
                                    label="Edit Data"
                                    onClick={getClickHandler(editDataState, null)}
                                    availableIcon={getFeatureIndicator(editDataState)}/>
                            </>
                        )}

                        {(shouldShow(createDiagramState) || shouldShow(createFromTemplateState) || shouldShow(manageDiagramsState)) && <Menu.Divider/>}

                        {shouldShow(createDiagramState) && (
                            <VrMenuItem
                                tip="Create a new diagram from scratch"
                                label="Create"
                                onClick={getClickHandler(createDiagramState, openCreate)}
                                availableIcon={getFeatureIndicator(createDiagramState)}/>
                        )}

                        {shouldShow(createFromTemplateState) && (
                            <VrMenuItem
                                tip="Create a new diagram from predefined template"
                                label="Create From Template"
                                onClick={getClickHandler(createFromTemplateState, null)}
                                availableIcon={getFeatureIndicator(createFromTemplateState)}/>
                        )}

                        {shouldShow(manageDiagramsState) && (
                            <VrMenuItem
                                tip="Manage Diagrams"
                                label="Manage"
                                onClick={getClickHandler(manageDiagramsState, openManage)}
                                availableIcon={getFeatureIndicator(manageDiagramsState)}/>
                        )}

                        {/* Export/Import JSON - Always available for creating templates */}
                        <VrMenuItem
                            tip="Export current diagram as JSON file (useful for creating templates)"
                            label="Export JSON"
                            onClick={handleExportJSON}
                            availableIcon={null}/>
                        <VrMenuItem
                            tip="Import entities from a previously exported JSON file"
                            label="Import JSON"
                            onClick={handleImportClick}
                            availableIcon={null}/>

                        {(shouldShow(shareCollaborateState) || shouldShow(configState)) && <Menu.Divider/>}

                        {shouldShow(shareCollaborateState) && (
                            <VrMenuItem
                                tip="Share your model with others. Creates a shareable link that copies to clipboard."
                                label="Share"
                                onClick={getClickHandler(shareCollaborateState, handleShare)}
                                availableIcon={getFeatureIndicator(shareCollaborateState)}/>
                        )}

                        {shouldShow(configState) && (
                            <VrMenuItem
                                tip="Configure settings for your VR experience"
                                label="Config"
                                onClick={getClickHandler(configState, openConfig)}
                                availableIcon={getFeatureIndicator(configState)}/>
                        )}

                        <Menu.Divider/>
                        <VrMenuItem
                            tip="Toggle AI chat assistant for creating entities"
                            label={chatOpen ? "Hide Chat" : "Show Chat"}
                            onClick={() => setChatOpen(!chatOpen)}
                            availableIcon={<IconMessageCircle size={16}/>}/>
                    </Menu.Dropdown>
                </Menu>
                {/* Hidden file input for JSON import */}
                <input
                    type="file"
                    ref={fileInputRef}
                    onChange={handleFileImport}
                    accept=".json"
                    style={{ display: 'none' }}
                />
            </Affix>

            <div style={{display: 'flex', height: '100vh', width: '100vw', overflow: 'hidden'}}>
                <div style={{flex: 1, position: 'relative', minWidth: 0}}>
                    <canvas id="vrCanvas" style={{
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        width: '100%',
                        height: '100%',
                        zIndex: 1
                    }}/>
                </div>
                {chatOpen && <ChatPanel onClose={() => setChatOpen(false)}/>}
            </div>

            {/* VR Entry Prompt - Rendered AFTER canvas to ensure it's on top in DOM order */}
            <VREntryPrompt
                isVisible={showVRPrompt}
                onEnterVR={() => {
                    setShowVRPrompt(false);
                    const event = new CustomEvent('enterXr', {bubbles: true});
                    window.dispatchEvent(event);
                }}
                onSkip={() => setShowVRPrompt(false)}
            />
        </VrTemplate>
        </React.StrictMode>
    )
}