import clsx from "clsx";
import { useState } from "react";
import {
  LoaderFunctionArgs,
  useLoaderData,
  useNavigate,
} from "react-router-dom";
import { createImporterStatusPageURL } from "#lib/urls";
import { fetchHasPendingDMs } from "#api/dms";
import { fetchImportLogs } from "#api/imports";
import { getLocalStorageItem, setLocalStorageItem } from "#storage/local";
import { useInterval } from "#hooks";
import { PageSkeleton } from "#components/pages";
import { LoadingIcon } from "#components/loading";
import { Button } from "#components/buttons";

interface IProps {
  importID: string;
  isDMS?: boolean;
  logs: string[];
}

export function ImporterStatusPage() {
  const { importID, isDMS, logs } = useLoaderData() as IProps;
  const navigate = useNavigate();
  const [isReversed, switchReversed] = useState(false);
  const title = `Import ${importID}`;
  const heading = `Importer logs for ${importID}`;
  const status = logs.length === 0 ? "Fetching" : "In Progress";
  const cooldown = 120_000;

  useInterval(() => {
    navigate(String(createImporterStatusPageURL(importID)));
  }, cooldown);

  return (
    <PageSkeleton name="importer-status" title={title} heading={heading}>
      {isDMS && (
        <div className="jumbo no-posts">
          <strong>Hey!</strong>
          <p>
            You gave the importer permission to access your messages. To protect
            your anonymity, you must manually approve each one. Wait until{" "}
            <i>after</i> the importer says <code>Done importing DMs</code>, then
            go <a href="/account/review_dms">here</a> to choose which ones you
            wish to import.
          </p>
        </div>
      )}

      <div className="import">
        <div className="import__info">
          <div className="import__stats">
            <div className="import__status">
              <span>Status: </span>
              <span>{status}</span>
            </div>

            <div
              className={clsx(
                "import__count",
                logs.length === 0 && "import__count--invisible"
              )}
            >
              <span>Total: </span>
              <span>{logs.length}</span>
            </div>
          </div>

          <div className="import__buttons">
            <Button
              className="import__reverse"
              onClick={() => switchReversed((old) => !old)}
            >
              Reverse order
            </Button>
          </div>
        </div>

        <p
          className={clsx(
            "loading-placeholder",
            logs.length !== 0 && "loading-placeholder--complete"
          )}
        >
          <LoadingIcon /> <span>Wait until logs load...</span>
        </p>

        <ol
          id="log-list"
          className={clsx(
            "log-list",
            logs.length !== 0 && "log-list--loaded",
            isReversed && "log-list--reversed"
          )}
        >
          {logs.length !== 0 &&
            logs.map((message, index) => (
              <li key={`${index}-${message}`} className="log-list__item">
                {message}
              </li>
            ))}
        </ol>
      </div>
    </PageSkeleton>
  );
}

async function initPendingReviewDms(
  forceReload = false,
  minutesForRecheck = 30
) {
  let hasPendingReviewDms =
    getLocalStorageItem("has_pending_review_dms") === "true";
  const lastCheckedHasPendingReviewDms = parseInt(
    getLocalStorageItem("last_checked_has_pending_review_dms") ?? "0",
    10
  );

  if (
    forceReload ||
    !lastCheckedHasPendingReviewDms ||
    lastCheckedHasPendingReviewDms < Date.now() - minutesForRecheck * 60 * 1000
  ) {
    /**
     * @type {string}
     */
    hasPendingReviewDms = await fetchHasPendingDMs();
    setLocalStorageItem("has_pending_review_dms", String(hasPendingReviewDms));
    localStorage.setItem(
      "last_checked_has_pending_review_dms",
      Date.now().toString()
    );
  }
}

export async function loader({
  params,
  request,
}: LoaderFunctionArgs): Promise<IProps> {
  const searchparams = new URL(request.url).searchParams;

  const importID = params.import_id?.trim();
  if (!importID) {
    throw new Error("Import ID is required.");
  }

  let isDMS: boolean | undefined = undefined;
  {
    const inputValue = Boolean(searchparams.get("dms")?.trim());
    if (inputValue) {
      isDMS = inputValue;
    }
  }

  const logs = await fetchImportLogs(importID);

  if (logs.length !== 0) {
    initPendingReviewDms(true);
  }

  return {
    importID,
    isDMS,
    logs,
  };
}
