import React, { useEffect, useMemo } from 'react';
import { RPCDetail } from './components/RPCDetail';
import { DocsMenuList } from './components/DocsMenuList';
import { useParams } from 'react-router';
import './index.css';
import axios from 'axios';
import { useState } from 'react';
import { Card, Loading } from '@therms/atalaya';
import { ErrorBoundary } from '../../../../../components/ErrorBoundary';
import { addAdditionalPropertiesFalse } from './util/json-docs-add-additional-properties-false';
import urlJoin from "url-join";

const DocsIndex = () => {
  const [docs, setDocs] = useState([]);
  const [heartbeats, setHeartbeats] = useState([]);
  const params = useParams();
  const [loading, setLoading] = useState(false);

  useEffect(async () => {
    try {
      const response = await axios.get(
        urlJoin(window.TELEMETRY_SERVER_URL || '/', '/docs'),
      );

      // we don't want additionalProperties to be true on any schemas
      addAdditionalPropertiesFalse(response.data);

      setDocs(response.data);
      setLoading(true);
    } catch (error) {
      alert('No documentation found, please refresh the page and try again.');
      console.log(error);
    }
    try {
      const response = await axios.get(
        urlJoin(window.TELEMETRY_SERVER_URL || '/', '/heartbeats'),
      );
      setHeartbeats(response.data);
    } catch (error) {
      alert('No servers found, please refresh the page and try again.');
      console.log(error);
    }
  }, []);

  const rpcScopeProcedure = useMemo(() => {
    return docs.reduce(
      function (acc, obj) {
        if (!acc.proceduresByScope[obj.scope]) {
          acc.proceduresByScope[obj.scope] = [];
          acc.allProceduresByScope[obj.scope] = {};
          acc.versionsByScopeProcedure[obj.scope] = [];
        }

        if (!acc.allProceduresByScope[obj.scope][obj.procedure]) {
          acc.allProceduresByScope[obj.scope][obj.procedure] = [];
        }

        const doesProcedureExist = acc.proceduresByScope[obj.scope].find(
          (procedure) => procedure === obj.procedure,
        );

        if (!doesProcedureExist) {
          acc.proceduresByScope[obj.scope].push(obj.procedure);
        }
        acc.allProceduresByScope[obj.scope][obj.procedure].push(obj);

        if (!acc.versionsByScopeProcedure[obj.scope][obj.procedure]) {
          acc.versionsByScopeProcedure[obj.scope][obj.procedure] = [];
        }

        // only add if the version doesn't exist in the array already
        if (
          !acc.versionsByScopeProcedure[obj.scope][obj.procedure].includes(
            obj.version,
          )
        ) {
          acc.versionsByScopeProcedure[obj.scope][obj.procedure].push(
            obj.version,
          );
        }

        return acc;
      },
      {
        proceduresByScope: {
          /*
            ExampleSchema:
            "scope": ["procedure"]
          */
        },
        allProceduresByScope: {
          /*
            ExampleSchema:
            "scope": {"procedure": [{RPC procedure version 1}, {RPC procedure version 2}]}
          */
        },
        versionsByScopeProcedure: {
          /*
            ExampleSchema:
            "scope": ["procedure": [All RPC procedure version numbers]]
          */
        },
      },
    );
  }, [docs]);

  return (
    <ErrorBoundary>
      <div className="container">
        {loading == true && (
          <>
            <div className="menu-container">
              <Card className="menu-list ">
                <ErrorBoundary>
                  <DocsMenuList
                    rpcListAll={docs}
                    rpcScopeProcedure={rpcScopeProcedure}
                  />
                </ErrorBoundary>
              </Card>
            </div>

            <div className="details-container">
              <Card className="bg-surface-subtle p-2 ">
                <ErrorBoundary>
                  <RPCDetail
                    rpcListAll={docs}
                    rpcScopeProcedure={rpcScopeProcedure}
                    heartbeats={heartbeats}
                  />
                </ErrorBoundary>
              </Card>
            </div>
          </>
        )}
        {loading == false && (
          <div className="w-full h-full">
            <Loading
              size="2xl"
              overlay
              message="Loading in progress. Please stand by."
            />
          </div>
        )}
      </div>
    </ErrorBoundary>
  );
};

DocsIndex.propTypes = {};

export { DocsIndex };
