import "./index.css";

import { StrictMode, useLayoutEffect, useRef, useState, useEffect, useMemo } from "react";
import { createRoot } from "react-dom/client";
import { useParams, Navigate, BrowserRouter, Link, Outlet, Route, Routes } from "react-router";
import { useShallow } from "zustand/shallow";
import { marked } from "marked";
import { apiInstance, resourcesInstance } from "./api.js";
import { useStore } from "./store.js";
import {
  ArrowBackIcon,
  ArrowForwardIcon,
  MenuBookIcon,
  MyLocationIcon,
  TitleIcon,
  WidthIcon,
  EllipsisIcon,
  CloseIcon,
  JustifyTextIcon,
  TextIncreaseIcon,
  TextDecreaseIcon,
  VRuleIcon,
} from "./icons/Icons";

createRoot(document.getElementById("root")).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<TopicListView />} />
          <Route path=":topicId" element={<FileReader />} />
        </Route>
      </Routes>
    </BrowserRouter>
  </StrictMode>,
);

function Layout() {
  const params = useParams();
  const topic = useStore((state) => params.topicId && state.topics.byId[params.topicId]);
  const config = useStore((state) => state.config);

  return (
    <div className="max-w-7xl mx-auto h-full relative flex flex-col">
      {config.displayTitle && (
        <div className="w-full px-4 py-2 font-medium text-large text-white bg-blue-600">
          <span>{topic ? `${topic.index + 1}: ${topic.title}` : "Конспект за Държавен Изпит"}</span>
        </div>
      )}
      <Outlet />
    </div>
  );
}

const SUBJECTS = [
  { id: 0, name: "ВЪТРЕШНИ БОЛЕСТИ" },
  { id: 1, name: "ФАРМАКОЛОГИЯ" },
];
export function TopicListView() {
  const itemRefs = useRef({});
  const topics = useStore(
    useShallow((state) => state.topics.allIds.map((id) => state.topics.byId[id])),
  );
  const selectedTopic = useStore((state) => state.selectedTopic);
  const selectTopic = useStore((state) => state.selectTopic);
  const selectedSubjectIndex = useStore((state) => state.subject);
  const setSelectedSubjectIndex = useStore((state) => state.selectSubject);
  const config = useStore((state) => state.config);
  const changeConfig = useStore((state) => state.changeConfig);

  const [isSelectingSubject, setIsSelectingSubject] = useState(false);

  useLayoutEffect(() => {
    if (selectedTopic && selectedTopic.id !== null) {
      itemRefs.current?.[Math.max(selectedTopic.index - 3, 0)].scrollIntoView();
    }
  }, [selectedTopic]);

  return (
    <>
      <div
        className={`flex-1 overflow-y-scroll ${selectedTopic === null ? "pb-[92px]" : "pb-[156px]"}`}
      >
        {topics.map((topic, i) => (
          <Link
            key={topic.id}
            ref={(node) => {
              itemRefs.current[i] = node;
            }}
            to={`/${topic.id}`}
            onClick={() => selectTopic(topic.id)}
            className={`flex px-2 py-1 rounded-md cursor-pointer border-l-4 ${topic.id === selectedTopic?.id ? "bg-blue-100 border-blue-500" : "border-transparent hover:bg-gray-100"}`}
          >
            <div
              className={`w-6 flex-shrink-0 flex font-medium justify-end ${topic.id === selectedTopic?.id ? "text-blue-600" : "text-blue-800"}`}
            >
              {i + 1}
            </div>
            <span
              className={`ml-2 leading-5 ${topic.id === selectedTopic?.id ? "font-medium" : "font-normal"} ${config.wrapTopicTitles ? "truncate" : ""}`}
            >
              {topic.title}
            </span>
          </Link>
        ))}
      </div>
      <div className="absolute bottom-0 sm:p-4 px-2 py-0 w-full flex flex-col">
        <div className="ml-auto p-2 flex space-x-1 h-[60px]">
          <button
            className={`cursor-pointer p-2 rounded-full text-white border ${config.displayTitle ? "bg-blue-100 border-blue-400" : "bg-gray-100 border-gray-400"}`}
            onClick={() => changeConfig({ displayTitle: !config.displayTitle })}
          >
            <TitleIcon className="fill-gray-600" />
          </button>

          <button
            className={`cursor-pointer p-2 rounded-full text-white border ${config.wrapTopicTitles ? "bg-blue-100 border-blue-400" : "bg-gray-100 border-gray-400"}`}
            onClick={() => changeConfig({ wrapTopicTitles: !config.wrapTopicTitles })}
          >
            <EllipsisIcon className="fill-gray-600" />
          </button>

          {selectedTopic !== null && (
            <button
              className="px-3 py-3 bg-teal-500 hover:bg-teal-300 cursor-pointer rounded-full flex items-center justify-center shadow-md transition-colors"
              onClick={() => {
                itemRefs.current?.[Math.max(selectedTopic.index - 3, 0)].scrollIntoView({
                  behavior: "smooth",
                });
              }}
            >
              <MyLocationIcon className="h-5 w-5" />
            </button>
          )}
          <div className="relative flex ml-2">
            <button
              className={`${isSelectingSubject ? "invisible" : ""} flex-1 shadow-xl cursor-pointer px-2 py-1 rounded-md text-xs text-blue-800 font-medium whitespace-nowrap bg-blue-100/50 backdrop-blur hover:bg-blue-200/50 border border-blue-100`}
              onClick={() => setIsSelectingSubject(true)}
            >
              {SUBJECTS[selectedSubjectIndex].name}
            </button>
            {isSelectingSubject && (
              <>
                <button
                  className={`absolute w-full h-full flex-1 flex justify-center items-center cursor-pointer rounded-md backdrop-blur bg-blue-100/40 hover:bg-blue-100/80`}
                  onClick={() => setIsSelectingSubject(false)}
                >
                  <CloseIcon className="fill-gray-600" />
                </button>
                <div className="absolute bottom-full right-0 p-2 flex space-x-1">
                  {SUBJECTS.map((subject) => (
                    <button
                      key={subject.id}
                      className={`flex-1 shadow-xl cursor-pointer px-2 py-1 rounded-md text-xs whitespace-nowrap h-[44px] ${
                        selectedSubjectIndex === subject.id
                          ? "bg-blue-100 text-blue-800 font-medium border border-blue-400"
                          : "bg-gray-100 hover:bg-gray-200 border border-gray-400"
                      }`}
                      onClick={() => {
                        setSelectedSubjectIndex(subject.id);
                        setIsSelectingSubject(false);
                      }}
                    >
                      {subject.name}
                    </button>
                  ))}
                </div>
              </>
            )}
          </div>
        </div>
        {selectedTopic !== null && (
          <Link
            to={`/${selectedTopic.id}`}
            className="w-full p-2 mb-2 bg-blue-600 hover:bg-blue-700 cursor-pointer truncate rounded-md text-sm text-white text-center shadow-md transition-colors"
          >
            <span>Продължи четенето:</span>
            <br />
            <span className="font-medium">
              {selectedTopic.index + 1}. {selectedTopic.title}
            </span>
          </Link>
        )}
      </div>
    </>
  );
}

export function FileReader() {
  const params = useParams();
  const topicsById = useStore((state) => state.topics.byId);
  const selectTopic = useStore((state) => state.selectTopic);

  const topic = topicsById[params.topicId];
  if (!topic) {
    return <Navigate to="/" replace />;
  }

  selectTopic(topic.id);

  return <Reader topic={topic} />;
}

export function Reader({ topic }) {
  const config = useStore((state) => state.config);
  const changeConfig = useStore((state) => state.changeConfig);
  const selectedVersion = useStore((state) => state.topicVersions[topic.id] ?? 0);
  const selectVersion = useStore((state) => state.selectTopicVersion);
  const getTopicAtIndex = useStore((state) => state.getTopicAtIndex);

  const prevTopic = getTopicAtIndex(topic.index - 1);
  const nextTopic = getTopicAtIndex(topic.index + 1);

  const [isSelectingVersion, setIsSelectingVersion] = useState(false);

  return (
    <>
      <div className="flex-1">
        <PDFViewer
          file={topic.files[selectedVersion]}
          compact={config.narrowMode}
          justifyText={config.justifyText}
          zoomFactor={config.contentZoomFactor}
        />
        <div className="absolute bottom-10 flex justify-between px-4 py-2 w-full z-999">
          <div className="flex w-full space-x-2">
            <Link to="/" className="cursor-pointer p-2 rounded-full bg-blue-600 text-white mr-auto">
              <MenuBookIcon className="fill-gray-100" />
            </Link>
          </div>
          <div className="flex items-center">
            <div className="text-sm text-gray-600 rounded bg-gray-300/30 backdrop-blur px-2">
              {config.contentZoomLevel}%
            </div>

            <button
              className={`cursor-pointer p-2 mx-1 rounded-full text-white bg-gray-100/30 backdrop-blur`}
              onClick={() =>
                changeConfig({ contentZoomLevel: Math.max(50, config.contentZoomLevel - 10) })
              }
            >
              <TextDecreaseIcon className="fill-gray-600" />
            </button>

            <button
              className={`cursor-pointer p-2 rounded-full text-white bg-gray-100/30 backdrop-blur`}
              onClick={() => {
                changeConfig({ contentZoomLevel: Math.min(150, config.contentZoomLevel + 10) });
              }}
            >
              <TextIncreaseIcon className="fill-gray-600" />
            </button>

            <VRuleIcon className="fill-gray-300" />

            <button
              className={`cursor-pointer p-2 mr-1 rounded-full text-white border ${config.displayTitle ? "bg-blue-100 border-blue-400" : "bg-gray-100 border-gray-400"}`}
              onClick={() => changeConfig({ displayTitle: !config.displayTitle })}
            >
              <TitleIcon className="fill-gray-600" />
            </button>

            <button
              className={`cursor-pointer p-2 mr-1 rounded-full text-white border ${config.justifyText ? "bg-blue-100 border-blue-400" : "bg-gray-100 border-gray-400"}`}
              onClick={() => changeConfig({ justifyText: !config.justifyText })}
            >
              <JustifyTextIcon className="fill-gray-600" />
            </button>

            {window.innerWidth > 576 && (
              <button
                className={`cursor-pointer p-2 mr-1 rounded-full text-white border ${config.narrowMode ? "bg-blue-100 border-blue-400" : "bg-gray-100 border-gray-400"}`}
                onClick={() => changeConfig({ narrowMode: !config.narrowMode })}
              >
                <WidthIcon className="fill-gray-600" />
              </button>
            )}
            {topic.files.length > 1 && (
              <div className="relative flex ml-2">
                <button
                  key={topic.files[selectedVersion].file}
                  className={`${isSelectingVersion ? "invisible" : ""} flex-1 shadow-xl cursor-pointer px-2 py-1 rounded-md text-xs text-blue-800 font-medium whitespace-nowrap bg-blue-100/50 backdrop-blur hover:bg-blue-200/50 border border-blue-100`}
                  onClick={() => setIsSelectingVersion(true)}
                >
                  Версия {selectedVersion + 1}
                </button>
                {isSelectingVersion && (
                  <button
                    key={topic.files[selectedVersion].file}
                    className={`absolute w-full h-full flex-1 flex justify-center items-center cursor-pointer rounded-md hover:backdrop-blur hover:bg-blue-100/30`}
                    onClick={() => setIsSelectingVersion(false)}
                  >
                    <CloseIcon className="fill-gray-600" />
                  </button>
                )}
              </div>
            )}
          </div>
          {isSelectingVersion && (
            <div className="absolute bottom-full right-0 px-4 flex space-x-1 h-10">
              {topic.files.map((file, vIndex) => (
                <button
                  key={file}
                  className={`flex-1 shadow-xl cursor-pointer px-2 py-1 rounded-md text-xs whitespace-nowrap ${
                    selectedVersion === vIndex
                      ? "bg-blue-100 text-blue-800 font-medium border border-blue-400"
                      : "bg-gray-100 hover:bg-gray-200 border border-gray-400"
                  }`}
                  onClick={() => {
                    selectVersion(topic.id, vIndex);
                    setIsSelectingVersion(false);
                  }}
                >
                  Версия {vIndex + 1}
                </button>
              ))}
            </div>
          )}
        </div>
      </div>
      <div className="w-full flex flex-col space-y-2">
        <div className="flex bg-gray-100 border-t border-blue-200 text-center">
          {topic.isFirst ? (
            <div className="flex-1 border-r border-blue-200" />
          ) : (
            <Link
              to={`/${prevTopic.id}`}
              className="border-r border-blue-200 w-1/2 flex-1 px-4 py-2 hover:bg-blue-200 cursor-pointer flex align-center justify-start"
            >
              <ArrowBackIcon />
              <span className="ml-2 truncate w-full ">
                {prevTopic.index + 1}: {prevTopic.title}
              </span>
            </Link>
          )}
          {topic.isLast ? (
            <div className="flex-1" />
          ) : (
            <Link
              to={`/${nextTopic.id}`}
              className="flex-1 px-4 py-2 hover:bg-blue-200 w-1/2 cursor-pointer flex align-center justify-end"
            >
              <span className="mr-2 w-full truncate">
                {nextTopic.index + 1}: {nextTopic.title}
              </span>
              <ArrowForwardIcon />
            </Link>
          )}
        </div>
      </div>
    </>
  );
}

export function PDFViewer({ file, compact, zoomFactor, justifyText }) {
  const iframeRef = useRef(null);
  const [content, setContent] = useState(null);
  const htmlContent = useMemo(() => {
    const fileContent = `
            <!DOCTYPE html>
            <html>
            <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
              <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.4.0/github-markdown-light.min.css">
              <style>
                body {
                  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
                  line-height: 1.5;
                  color: #333;
                  -webkit-font-smoothing: antialiased;
                  -moz-osx-font-smoothing: grayscale;
                  margin: 0;
                  padding: 0 12px 40px;
                  ${compact ? `max-width: calc(36rem / ${zoomFactor}); margin: 0 auto;` : ""}
                }
                ${
                  justifyText
                    ? `
                  p {
                    text-align: justify;
                    text-justify: inter-word;
                  }
                  pre, code {
                    font-family: 'SF Mono', Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
                  }
                `
                    : ""
                }
              </style>
            </head>
            <body>
              ${content}
            </body>
            </html>
          `;
    return fileContent;
  }, [content, compact, justifyText, zoomFactor]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  const contentZoomLevel = useStore((state) => state.config.contentZoomLevel);

  useEffect(() => {
    if (iframeRef.current && iframeRef.current.contentDocument) {
      iframeRef.current.contentDocument.body.style.zoom = `${contentZoomLevel}%`;
    }
  }, [contentZoomLevel]);

  useEffect(() => {
    const fetchFile = async () => {
      try {
        setIsLoading(true);
        const mdPath = `/files_md/${file.filename}`;
        const response = await fetch(mdPath);

        if (!response.ok) {
          throw new Error(`Failed to load file: ${response.status}`);
        }

        let fileContent = await response.text();
        if (fileContent === "") {
          fileContent = "**No Data!**";
        }
        fileContent = marked.parse(fileContent);

        setContent(fileContent);
        setError(null);
      } catch (err) {
        console.error("Error loading file:", err);
        setError(err.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchFile();
  }, [file]);

  if (error) {
    return <div className="text-red-500 p-4 border border-red-300 rounded">Error: {error}</div>;
  }

  if (isLoading) {
    return <DelayedLoader />;
  }

  return (
    <div className={`w-full h-full overflow-hidden`}>
      <iframe
        ref={iframeRef}
        srcDoc={htmlContent}
        title={`File: ${file}`}
        className="w-full h-full border-0"
        key={file}
        allow="fullscreen"
        onLoad={() => {
          if (iframeRef.current?.contentDocument?.body) {
            iframeRef.current.contentDocument.body.style.zoom = `${contentZoomLevel}%`;
          }
        }}
      />
    </div>
  );
}

const DelayedLoader = ({
  delayMs = 2000,
  className = "p-4 flex justify-center items-center h-40",
  text = "Loading...",
}) => {
  const [showLoader, setShowLoader] = useState(false);

  useEffect(() => {
    // Set a timeout to show the loader after the specified delay
    const timer = setTimeout(() => {
      setShowLoader(true);
    }, delayMs);

    // Clear the timeout on unmount
    return () => clearTimeout(timer);
  }, []); // Empty dependency array - only run on mount

  // Only render if the delay has passed
  if (showLoader) {
    return (
      <div className={className}>
        <div className="animate-pulse">{text}</div>
      </div>
    );
  }

  // Return null before delay threshold
  return null;
};
