import { useAtom } from "jotai";
import { AnimatePresence, motion } from "motion/react";
import {
  BiCheckCircle,
  BiCopy,
  BiLeftArrowAlt,
  BiLink,
  BiPlus,
  BiPlusCircle,
  BiTrash,
  BiX,
} from "react-icons/bi";
import Logo from "../assets/logo.svg";
import {
  AdminUpdateRequest,
  ClassUpdateRequest,
  getClassProfile,
} from "../trash/req_mgr";
import { API_BASE_URL } from "../App";
import { useEffect, useRef, useState } from "react";
import {
  DengiButton,
  DengiEditable,
  DengiYesOrNoDialog,
  LoadingSpinner,
  TextPreloader,
} from "../trash/trash-components";
import { b64e, copyDXLink, randomString } from "../trash/helpers";
import { AvailableAdminSymbols } from "../trash/dengi";

export default function AdminProfilePage({
  classIDAtom,
  adminAtom,
  setsetRoute,
  routeAtom,
  pickmeModeAtom,
}) {
  const [pickmeMode, _] = useAtom(pickmeModeAtom);
  const [_route, setRoute] = useAtom(routeAtom);
  const [adminId, _setAdminId] = useAtom(adminAtom);
  const [classId, _setClassId] = useAtom(classIDAtom);
  const [error, setError] = useState("");
  const [classData, setClassData] = useState(false);
  const [adminsData, setAdminsData] = useState(false);
  const [dataId, setDataId] = useState(0);
  if (classId === "") {
    setsetRoute(setRoute, "/");
  }
  useEffect(() => {
    let cancelled = false;

    (async () => {
      const a = (await getClassProfile(API_BASE_URL, adminId)) || false;
      if (!cancelled && a[0] === 1) {
        if (a[1]["class"]) {
          setClassData(a[1]["class"]);
          setAdminsData(a[1]["admins"]);
        } else {
          setError(a[1]);
        }
      } else {
        setError(a[1]);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [adminId, dataId]);
  return (
    <>
      <motion.div className="w-full h-screen flex flex-col items-center justify-center gap-5 overflow-x-hidden z-2">
        <motion.div
          className="w-screen h-screen flex flex-col items-center sm:max-w-[500px] sm:max-h-[90vh] gap-3"
          initial={{ scale: 0.99, opacity: 0, y: 5 }}
          animate={{ scale: 1, opacity: 1, y: 0 }}
        >
          <Header {...{ setsetRoute, setRoute, pickmeMode }} />
          <span className="text-xl font-bold text-center">
            управление классом
          </span>
          {error && typeof error == "string" && (
            <span className="text-red-500 text-2xl">{error}</span>
          )}
          <ClassProfileEditor
            {...{
              classId,
              loaded: classData !== false,
              classFr: classData.userclassname,
              pickmeMode,
              adminId,
              adminsData,
              update: () => {
                setDataId(dataId + 1);
              },
              setAdminsData,
              setClassFr: (v) => {
                setClassData((prev) => ({ ...prev, userclassname: v }));
              },
            }}
          />
        </motion.div>
      </motion.div>
      <CoolBg {...{ pickmeMode }} />
    </>
  );
}

export function ClassProfileEditor({
  classId,
  classFr,
  pickmeMode,
  loaded,
  adminId,
  adminsData,
  setClassFr,
  update,
  setAdminsData,
}) {
  return (
    <div className="flex flex-col items-center bg-grain gap-2 bg-zinc-800/50 p-5 rounded-2xl not-md:w-[90%] relative md:min-w-[520px]">
      <table className="">
        <tbody className="*:*:min-w-20 *:*:h-10">
          <tr>
            <td className="">classId</td>
            <td className="font-mono text-center select-all selectable">
              {classId}
            </td>
          </tr>
          <tr>
            <td className="">название</td>
            <td className="w-40">
              <DengiEditable
                value={loaded ? classFr : false}
                pink={pickmeMode}
                onSubmit={async (e) => {
                  e.setIdle(true);
                  let r = await ClassUpdateRequest(API_BASE_URL, adminId, {
                    action: "update_name",
                    value: e.value.trim(),
                  });
                  if (r[1] == true) setClassFr(e.value.trim());
                  e.setIdle(false);
                }}
              />
            </td>
          </tr>
        </tbody>
      </table>
      <div className="w-50 mt-5">
        <CopyClassLink {...{ classId }} />
      </div>
      <span className="h-[1px] w-[80%] bg-zinc-700 block my-5 "></span>
      <span className="text-xl font-bold block">админы</span>
      <table className="w-full">
        <thead>
          <tr className="*:px-2">
            <th>имя</th>
            <th>id</th>
            <th>уров.</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          {adminsData &&
            adminsData.map((i) => (
              <AdminProfileRow
                key={i.adminId}
                {...{
                  adminId: i.adminId,
                  editorAdminId: adminId,
                  adminName: i.adminName,
                  adminLevel: i.adminPrems,
                  classId,
                  update,
                  pickmeMode,
                  setAdminFrId: (v) => {
                    setAdminsData((prev) =>
                      prev.map((a) =>
                        a.adminId === i.adminId ? { ...a, adminName: v } : a
                      )
                    );
                  },
                }}
              />
            ))}
          {!loaded && (
            <tr>
              <td>
                <span className="flex w-full justify-center">
                  <TextPreloader />
                </span>
              </td>
              <td>
                <span className="flex w-full justify-center">
                  <TextPreloader />
                </span>
              </td>
              <td>
                <span className="flex w-full justify-center">
                  <TextPreloader />
                </span>
              </td>
              <td>
                <LoadingSpinner size={20} />
              </td>
            </tr>
          )}
        </tbody>
      </table>
      {loaded && <CreateAdmin {...{ editorAdminId: adminId, update }} />}
    </div>
  );
}

function CreateAdmin({ editorAdminId, update }) {
  const [creating, setCreating] = useState(false);
  const [adminId, setAdminId] = useState("");
  const [adminName, setAdminName] = useState("");
  const [locked, setLocked] = useState(false);
  const form = useRef(null);
  return (
    <>
      <div className="flex w-full gap-1">
        <span className="w-full" />
        <AnimatePresence>
          {creating && (
            <motion.form
              className="flex gap-2"
              variants={{
                off: { opacity: 0, x: 20 },
                on: { opacity: 1, x: 0 },
              }}
              initial="off"
              animate="on"
              exit="off"
              ref={form}
              onSubmit={async (e) => {
                e.preventDefault();
                if (locked || adminId.length < 5) return;
                setLocked(true);
                const c = await ClassUpdateRequest(
                  API_BASE_URL,
                  editorAdminId,
                  {
                    action: "create_admin",
                    value: `${adminId};${b64e(adminName)}`,
                  }
                );
                if (c[1] == true) {
                  update();
                  setCreating(false);
                }
                setLocked(false);
              }}
            >
              <input
                className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2"
                placeholder="имя"
                required
                value={adminName}
                disabled={locked}
                maxLength={50}
                onInput={(e) => setAdminName(e.target.value.trimStart())}
              />
              <input
                className="bg-zinc-900 rounded-2xl border border-zinc-500/50 px-2"
                placeholder="adminId"
                value={adminId}
                required
                disabled={locked}
                maxLength={20}
                minLength={5}
                min={5}
                onInput={(e) => {
                  let val = e.target.value;
                  let nval = "";
                  val.split("").forEach((i) => {
                    if (AvailableAdminSymbols.includes(i)) {
                      nval = nval + i;
                    }
                  });
                  e.target.value = nval;
                  setAdminId(nval);
                }}
              />
              <button>
                <DengiButton>
                  {locked ? <LoadingSpinner /> : <BiPlus />}
                </DengiButton>
              </button>
            </motion.form>
          )}
        </AnimatePresence>
        <DengiButton
          disabled={locked}
          onClick={() => {
            setCreating(!creating);
            setAdminName("");
            setAdminId(randomString(8, AvailableAdminSymbols));
          }}
        >
          <span className={`${creating ? "rotate-45" : ""} transition`}>
            <BiPlusCircle />
          </span>
        </DengiButton>
      </div>
    </>
  );
}

function AdminProfileRow({
  adminId,
  editorAdminId,
  adminName,
  classId,
  pickmeMode,
  setAdminFrId,
  adminLevel,
  update,
}) {
  return (
    <tr className="h-12">
      <td className="px-2">
        <DengiEditable
          value={adminName}
          pink={pickmeMode}
          onSubmit={async (e) => {
            e.setIdle(true);
            const r = await AdminUpdateRequest(API_BASE_URL, editorAdminId, {
              action: "change_name",
              value: e.value.trim(),
              person: adminId,
            });
            if (r[1] == true) setAdminFrId(e.value);
            e.setIdle(false);
          }}
        />
      </td>
      <td className="px-2">
        <DengiEditable
          value={adminId}
          password={true}
          pink={pickmeMode}
          disabled
        />
      </td>
      <td className="text-center">{adminLevel}</td>
      <td className="inline-flex gap-1 items-center justify-center">
        <CopyAdminLink {...{ classId, adminId }} />
        <RemoveAdminButton
          {...{ adminId, editorAdminId, adminName, update }}
          disabled={[-1, 2].includes(adminLevel)}
        />
      </td>
    </tr>
  );
}

const RemoveAdminButton = ({
  adminId,
  editorAdminId,
  adminName,
  update,
  disabled,
}) => {
  const [showDiag, setShowDiag] = useState(false);
  const [deleting, setDeleting] = useState(false);

  return (
    <>
      <DengiYesOrNoDialog
        show={showDiag}
        content={{
          message: (
            <p>
              вы точно хотите удалить админа <b>{adminName}</b>?
            </p>
          ),
          yesBtn: "да",
          noBtn: "нет",
          yesIcon: <BiTrash />,
          noIcon: <BiX size={20} />,
          bgDissmis: true,
          yesBtnStyle: "bg-red-500! text-white! md:hover:bg-red-600!",
        }}
        onAnswer={async (answ) => {
          setShowDiag(false);
          if (answ) {
            setDeleting(true);
            const c = await ClassUpdateRequest(API_BASE_URL, editorAdminId, {
              action: "delete_admin",
              value: adminId,
            });
            if (c[1] == true) {
              update();
              setDeleting(false);
            }
          }
        }}
      />
      <DengiButton
        disabled={adminId === editorAdminId || disabled}
        onClick={() => {
          if (deleting) return;
          setShowDiag(true);
        }}
      >
        {deleting ? <LoadingSpinner size={20} /> : <BiTrash />}
      </DengiButton>
    </>
  );
};

const CopyClassLink = ({ classId }) => {
  const [linkCopied, setLinkCopied] = useState(false);

  return (
    <DengiButton
      onClick={() => {
        copyDXLink(classId).then((a) => {
          if (a) {
            setLinkCopied(true);
            setTimeout(() => {
              setLinkCopied(false);
            }, 2000);
          }
        });
      }}
    >
      <BiLink />
      <span>{linkCopied ? "скопировано" : "коп ссылку"}</span>
    </DengiButton>
  );
};
const CopyAdminLink = ({ classId, adminId }) => {
  const [showDiag, setShowDiag] = useState(false);
  const [seenDiag, setSeenDiag] = useState(false);
  const [linkCopied, setLinkCopied] = useState(false);
  const copy = () => {
    copyDXLink(classId, adminId).then((a) => {
      if (a) {
        setLinkCopied(true);
        setTimeout(() => {
          setLinkCopied(false);
        }, 2000);
      }
    });
  };
  return (
    <>
      <DengiYesOrNoDialog
        show={showDiag}
        content={{
          message: (
            <p>
              <b>любой</b>, кто получит ссылку,{" "}
              <b>будет иметь доступ к админке</b>.<br /> вы желаете продолжить?
            </p>
          ),
          yesBtn: "да",
          noBtn: "нет",
          yesIcon: <BiCopy />,
          noIcon: <BiX size={20} />,
          bgDissmis: true,
          yesBtnStyle: "bg-orange-500! text-white! md:hover:bg-orange-600!",
        }}
        onAnswer={(answ) => {
          if (answ) {
            setSeenDiag(true);
            copy();
          }
          setShowDiag(false);
        }}
      />
      <DengiButton onClick={() => (seenDiag ? copy() : setShowDiag(true))}>
        {linkCopied ? <BiCheckCircle /> : <BiLink />}
      </DengiButton>
    </>
  );
};

const CoolBg = ({ pickmeMode }) => {
  return (
    <>
      <div
        className={`fixed top-0 left-0 w-full h-full -z-5 overflow-hidden bg-gradient-to-tl to-black to-50% bg-fixed ${
          pickmeMode ? "from-pink-400/10" : "from-white/2"
        }`}
      />
    </>
  );
};

const Header = ({ setsetRoute, setRoute, pickmeMode }) => {
  return (
    <div className={"flex items-center w-full justify-between px-5"}>
      <span className="flex gap-2 items-center">
        <BiLeftArrowAlt
          size={35}
          onClick={() => {
            setsetRoute(setRoute, "/app");
          }}
          onContextMenu={(e) => {
            e.preventDefault();
          }}
          className={
            "rounded-full " +
            (pickmeMode
              ? "lg:hover:bg-pink-400"
              : "lg:hover:bg-white lg:hover:fill-black") +
            " lg:hover:scale-105 transition cursor-pointer"
          }
        />
        <img src={Logo} alt="logo" width={100} draggable={false} />
      </span>
    </div>
  );
};
