import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import useMediaQuery from '@mui/material/useMediaQuery';
import Card from '@mui/material/Card';
import { styled } from '@mui/material/styles';
import Avatar from '@mui/material/Avatar';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Tooltip from '@mui/material/Tooltip';
import AppBar from '@mui/material/AppBar';
import Drawer from '@mui/material/Drawer';
import Toolbar from '@mui/material/Toolbar';
import SettingsIcon from '@mui/icons-material/Settings';
import IconButton from '@mui/material/IconButton';
import Box from '@mui/material/Box';
import CssBaseline from '@mui/material/CssBaseline';
import MenuIcon from '@mui/icons-material/Menu';

import { Snack, SeverityType } from './Snack';
import { ConversationHandle } from './Conversation';
import { QueryOptions } from './ChatQuery';
import { Scrollable } from './Scrollable';
import { BackstoryPage, BackstoryTabProps } from './BackstoryTab';

import { connectionBase } from './Global';

import { HomePage } from './HomePage';
import { ResumeBuilderPage } from './ResumeBuilderPage';
import { VectorVisualizerPage } from './VectorVisualizer';
import { AboutPage } from './AboutPage';
import { ControlsPage } from './ControlsPage';


import './App.css';
import './Conversation.css';

import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';



const isValidUUIDv4 = (str: string): boolean => {
  const pattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i;
  return pattern.test(str);
}

const App = () => {
  const [sessionId, setSessionId] = useState<string | undefined>(undefined);
  const [menuOpen, setMenuOpen] = useState(false);
  const [isMenuClosing, setIsMenuClosing] = useState(false);
  const [activeTab, setActiveTab] = useState<number>(0);
  const isDesktop = useMediaQuery('(min-width:650px)');
  const prevIsDesktopRef = useRef<boolean>(isDesktop);
  const chatRef = useRef<ConversationHandle>(null);
  const snackRef = useRef<any>(null);
  const [subRoute, setSubRoute] = useState<string>("");

  useEffect(() => {
    if (prevIsDesktopRef.current === isDesktop)
      return;
    
    if (menuOpen) {
      setMenuOpen(false);
    }
    
    prevIsDesktopRef.current = isDesktop;
  }, [isDesktop, setMenuOpen, menuOpen])

  const setSnack = useCallback((message: string, severity?: SeverityType) => {
    snackRef.current?.setSnack(message, severity);
  }, [snackRef]);

  const handleSubmitChatQuery = (prompt: string, tunables?: QueryOptions) => {
    console.log(`handleSubmitChatQuery: ${prompt} ${tunables || {}} -- `, chatRef.current ? ' sending' : 'no handler');
    chatRef.current?.submitQuery(prompt, tunables);
    setActiveTab(0);
  };

  const tabs: BackstoryTabProps[] = useMemo(() => {
    const homeTab: BackstoryTabProps = {
      label: "",
      path: "",
      tabProps: {
        label: "Backstory",
        sx: { flexGrow: 1, fontSize: '1rem' },
        icon:
          <Avatar sx={{
            width: 24,
            height: 24
          }}
            variant="rounded"
            alt="Backstory logo"
            src="/logo192.png" />,
        iconPosition: "start"
      },
      children: <HomePage ref={chatRef} {...{ sessionId, setSnack, submitQuery: handleSubmitChatQuery, route: subRoute, setRoute: setSubRoute }} />
    };

    const resumeBuilderTab: BackstoryTabProps = {
      label: "Resume Builder",
      path: "resume-builder",
      children: <ResumeBuilderPage  {...{ sessionId, setSnack, submitQuery: handleSubmitChatQuery, route: subRoute, setRoute: setSubRoute }} />
    };

    const contextVisualizerTab: BackstoryTabProps = {
      label: "Context Visualizer",
      path: "context-visualizer",
      children: <VectorVisualizerPage sx={{ p: 1 }} {...{ sessionId, setSnack, submitQuery: handleSubmitChatQuery, route: subRoute, setRoute: setSubRoute }} />
    };

    const aboutTab = {
      label: "About",
      path: "about",
      children: <AboutPage {...{ sessionId, setSnack, submitQuery: handleSubmitChatQuery, route: subRoute, setRoute: setSubRoute }} />
    };

    const controlsTab: BackstoryTabProps = {
      path: "controls",
      tabProps: {
        sx: { flexShrink: 1, flexGrow: 0, fontSize: '1rem' },
        icon: <SettingsIcon />
      },
      children: (
        <Scrollable
          autoscroll={false}
          sx={{
            maxWidth: "1024px",
            height: "calc(100vh - 72px)",
            flexDirection: "column",
            margin: "0 auto",
            p: 1,
          }}
        >
          {sessionId !== undefined &&
            <ControlsPage {...{ sessionId, setSnack, submitQuery: handleSubmitChatQuery, route: subRoute, setRoute: setSubRoute }} />
          }
        </Scrollable>
      )
    };

    return [
      homeTab,
      resumeBuilderTab,
      contextVisualizerTab,
      aboutTab,
      controlsTab,
    ];
  }, [sessionId, setSnack, subRoute]);


  useEffect(() => {
    if (sessionId === undefined || activeTab > tabs.length - 1) { return; }
    console.log(`route - '${tabs[activeTab].path}', subRoute - '${subRoute}'`);

    let path = tabs[activeTab].path ? `/${tabs[activeTab].path}` : '';
    if (subRoute) {
      path += `/${subRoute}`;
    }
    path += `/${sessionId}`;
    console.log('pushState: ', path);
    //    window.history.pushState({}, '', path);
  }, [activeTab, sessionId, subRoute, tabs]);

  const fetchSession = useCallback((async (pathParts?: string[]) => {
    try {
      const response = await fetch(connectionBase + `/api/context`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        throw Error("Server is temporarily down.");
      }
      const new_session = (await response.json()).id;
      console.log(`Session created: ${new_session}`);

      if (pathParts === undefined) {
        setSessionId(new_session);
        const newPath = `/${new_session}`;
        window.history.replaceState({}, '', newPath);
      } else {
        const currentPath = pathParts.length < 2 ? '' : pathParts[0];
        let tabIndex = tabs.findIndex((tab) => tab.path === currentPath);
        if (-1 === tabIndex) {
          console.log(`Invalid path "${currentPath}" -- redirecting to default`);
          window.history.replaceState({}, '', `/${new_session}`);
          setActiveTab(0);
        } else {
          window.history.replaceState({}, '', `/${pathParts.join('/')}/${new_session}`);
          //          tabs[tabIndex].route = pathParts[2] || "";
          setActiveTab(tabIndex);
        }
        setSessionId(new_session);
      }
    } catch (error: any) {
      console.error(error);
      setSnack("Server is temporarily down", "error");
    }
  }), [setSnack, tabs]);

  useEffect(() => {
    const url = new URL(window.location.href);
    const pathParts = url.pathname.split('/').filter(Boolean); // [path, sessionId]

    if (pathParts.length < 1) {
      console.log("No session id or path -- creating new session");
      fetchSession();
    } else {
      const currentPath = pathParts.length < 2 ? '' : pathParts[0];
      const path_session = pathParts.length < 2 ? pathParts[0] : pathParts[1];
      if (!isValidUUIDv4(path_session)) {
        console.log(`Invalid session id ${path_session}-- creating new session`);
        fetchSession();
      } else {
        let tabIndex = tabs.findIndex((tab) => tab.path === currentPath);
        if (-1 === tabIndex) {
          console.log(`Invalid path "${currentPath}" -- redirecting to default`);
          tabIndex = 0;
        }
        //        tabs[tabIndex].route = pathParts[2] || ""
        setSessionId(path_session);
        setActiveTab(tabIndex);
      }
    }
  }, [setSessionId, setSnack, tabs, fetchSession]);

  const handleMenuClose = () => {
    setIsMenuClosing(true);
    setMenuOpen(false);
  };

  const handleMenuTransitionEnd = () => {
    setIsMenuClosing(false);
  };

  const handleMenuToggle = () => {
    if (!isMenuClosing) {
      setMenuOpen(!menuOpen);
    }
  };

  const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
    if (newValue > tabs.length) {
      return;
    }
    setActiveTab(newValue);
    const tabPath = tabs[newValue].path;
    let path = `/${sessionId}`;
    if (tabPath) {
      // if (openDocument) {
      //   path = `/${tabPath}/${openDocument}/${sessionId}`;
      // } else {
      path = `/${tabPath}/${sessionId}`;
      // }
    }
    window.history.pushState({}, '', path);
    handleMenuClose();
  };

  useEffect(() => {
    const handlePopState = () => {
      const url = new URL(window.location.href);
      const pathParts = url.pathname.split('/').filter(Boolean);
      const currentPath = pathParts.length < 2 ? '' : pathParts[0];
      const session = pathParts.length < 2 ? pathParts[0] : pathParts[1];

      let tabIndex = tabs.findIndex((tab) => tab.path === currentPath);
      if (-1 === tabIndex) {
        console.log(`Invalid path "${currentPath}" -- redirecting to default`);
        tabIndex = 0;
      }
      setSessionId(session);
      setActiveTab(tabIndex);
    };

    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, [setSessionId, tabs]);

  /* toolbar height is 64px + 8px margin-top */
  const Offset = styled('div')(() => ({ minHeight: '72px', height: '72px' }));

  return (
    <Box className="App"
      sx={{ display: 'flex', flexDirection: 'column' }}>
      <CssBaseline />
      <AppBar
        position="fixed"
        sx={{
          zIndex: (theme) => theme.zIndex.drawer + 1,
          maxWidth: "100vw"
        }}
      >
        <Toolbar>
          <Box sx={{ display: "flex", flexGrow: 1, flexDirection: "row" }}>
            {!isDesktop &&
              <Box sx={{ display: "flex", flexGrow: 1, flexDirection: "row" }}>
                <IconButton
                  sx={{ display: "flex", margin: 'auto 0px' }}
                  size="large"
                  edge="start"
                  color="inherit"
                  onClick={handleMenuToggle}
                >
                  <Tooltip title="Navigation">
                    <MenuIcon />
                  </Tooltip>
                </IconButton>
                <Tooltip title="Backstory">
                  <Box
                    sx={{ m: 1, gap: 1, display: "flex", flexDirection: "row", alignItems: "center", fontWeight: "bold", fontSize: "1.0rem", cursor: "pointer" }}
                    onClick={() => { setActiveTab(0); setMenuOpen(false); }}
                  >
                    <Avatar sx={{
                      width: 24,
                      height: 24
                    }}
                      variant="rounded"
                      alt="Backstory logo"
                      src="/logo192.png" />
                    BACKSTORY
                  </Box>
                </Tooltip>
              </Box>
            }

            {menuOpen === false && isDesktop &&
              <Tabs sx={{ display: "flex", flexGrow: 1 }}
                value={activeTab}
                indicatorColor="secondary"
                textColor="inherit"
                variant="fullWidth"
                allowScrollButtonsMobile
                onChange={handleTabChange}
                aria-label="Backstory navigation">
                {tabs.map((tab, index) => <Tab key={index} value={index} label={tab.label} {...tab.tabProps} />)}
              </Tabs>
            }
          </Box>
        </Toolbar>

      </AppBar>

      <Offset />

      <Box
        sx={{ display: "flex", flexGrow: 1, flexDirection: "column" }}
      >
        <Box
          component="nav"
          aria-label="mailbox folders"
        >
          <Drawer
            container={window.document.body}
            variant="temporary"
            open={menuOpen}
            onTransitionEnd={handleMenuTransitionEnd}
            onClose={handleMenuClose}
            sx={{
              display: 'block',
              '& .MuiDrawer-paper': { boxSizing: 'border-box' },
            }}
            slotProps={{
              root: {
                keepMounted: true, // Better open performance on mobile.
              },
            }}
          >
            <Toolbar />
            <Card className="MenuCard">
              <Tabs sx={{ display: "flex", flexGrow: 1 }}
                orientation="vertical"
                value={activeTab}
                indicatorColor="secondary"
                textColor="inherit"
                variant="scrollable"
                allowScrollButtonsMobile
                onChange={handleTabChange}
                aria-label="Backstory navigation">
                {tabs.map((tab, index) => <Tab key={index} value={index} label={tab.label} {...tab.tabProps} />)}
              </Tabs>
            </Card>
          </Drawer>
        </Box>
        {
          tabs.map((tab: any, i: number) =>
            <BackstoryPage key={i} active={i === activeTab} path={tab.path}>{tab.children}</BackstoryPage>
          )
        }
      </Box>

      <Snack
        ref={snackRef}
      />
    </Box >
  );
};

export default App;