import { FC, ReactNode, isValidElement, useEffect } from "react";
import * as card from "../ui/card";
import { cn } from "lib/utils";
import { useLocal } from "lib/utils/use-local";
import { Skeleton } from "../ui/skeleton";

export const Card: FC<{
  title: { left: ReactNode; right: ReactNode };
  desc:
    | ((arg: { setOnClick: (fn: any) => void }) => Promise<ReactNode>)
    | ReactNode;
  value: (() => Promise<ReactNode>) | ReactNode;
  bg: "default" | "transparent";
}> = ({ title, desc, value, bg }) => {
  const local = useLocal({
    value: "" as any,
    desc: "" as any,
    status_value: "init" as "init" | "loading" | "ready",
    status_desc: "init" as "init" | "loading" | "ready",
    onClick: null as null | (() => void),
  });

  useEffect(() => {
    if (!isEditor) {
      if (!!value && typeof value === "function") {
        local.status_value = "loading";
        local.render();
        const result = value();
        if (typeof result === "object" && result instanceof Promise) {
          result.then((val) => {
            local.value = val;
            local.status_value = "ready";
            local.render();
          });
        } else {
          local.value = result;
          local.status_value = "ready";
          local.render();
        }
      }

      if (!!desc && typeof desc === "function") {
        local.status_desc = "loading";
        local.render();
        const result = desc({
          setOnClick: (fn) => {
            local.onClick = fn;
            local.render();
          },
        });
        if (typeof result === "object" && result instanceof Promise) {
          result.then((val) => {
            local.desc = val;
            local.status_desc = "ready";
            local.render();
          });
        } else {
          local.desc = result;
          local.status_desc = "ready";
          local.render();
        }
      }
    }
  }, []);

  if (typeof desc !== "function") {
    local.status_desc = "ready";
    local.desc = desc;
  } else if (isEditor) {
    local.desc = typeof desc === "function" ? "..." : desc;
    local.status_desc = "ready";
  }

  if (typeof value !== "function") {
    local.status_value = "ready";
    local.value = value;
  } else if (isEditor) {
    local.value = "...";
    local.status_value = "ready";
  }

  return (
    <card.Card
      className={cx(
        "c-flex c-flex-1 c-items-center",
        bg === "transparent" &&
          css`
            background: none !important;
          `
      )}
      onClick={() => {
        if (local.onClick) {
          local.onClick();
        }
      }}
    >
      <div className={cn("c-p-3 c-text-[14px] c-flex-1")}>
        {!!title && (title.left || title.right) && (
          <div className="c-tracking-tight c-text-sm c-font-medium c-flex c-justify-between c-space-x-1 mb-1 c-items-center">
            <div className="c-flex">{title.left}</div>
            {title.right && (
              <div className="c-flex c-opacity-70 c-text-xs">{title.right}</div>
            )}
          </div>
        )}
        {!!value && (
          <card.CardTitle className="c-whitespace-nowrap pb-1 h-[28px] c-overflow-hidden">
            {local.status_value === "ready" ? (
              formatObject(local.value)
            ) : (
              <div className="flex flex-col space-y-1">
                <Skeleton className="h-[10px] c-w-[50px]" />
                <Skeleton className="h-[10px] c-w-[40px]" />
              </div>
            )}
          </card.CardTitle>
        )}
        <card.CardDescription className="c-text-xs c-whitespace-pre-wrap">
          {local.status_desc === "ready" ? (
            formatObject(local.desc)
          ) : (
            <div className="flex flex-col space-y-1">
              <Skeleton className="h-[10px] c-w-[50px]" />
            </div>
          )}
        </card.CardDescription>
      </div>
    </card.Card>
  );
};

const formatObject = (val: any) => {
  if (typeof val === "object") {
    if (isValidElement(val)) return val;
    else return JSON.stringify(val);
  }
  return val;
};
