import Button from "@/components/Low/Button";
import Checkbox from "@/components/Low/Checkbox";
import useUsers from "@/hooks/useUsers";
import { Code, User } from "@/interfaces/user";
import { USER_TYPE_LABELS } from "@/resources/user";
import { createColumnHelper } from "@tanstack/react-table";
import axios from "axios";
import moment from "moment";
import { useState, useMemo } from "react";
import { BsTrash } from "react-icons/bs";
import { toast } from "react-toastify";
import { EntityWithRoles } from "@/interfaces/entity";
import { isAdmin } from "@/utils/users";
import { findBy, mapBy } from "@/utils";
import useEntitiesCodes from "@/hooks/useEntitiesCodes";
import Table from "@/components/High/Table";

type TableData = Code & { entity?: EntityWithRoles; creator?: User };
const columnHelper = createColumnHelper<TableData>();

export default function CodeList({
  user,
  entities,
  canDeleteCodes,
}: {
  user: User;
  entities: EntityWithRoles[];
  canDeleteCodes?: boolean;
}) {
  const [selectedCodes, setSelectedCodes] = useState<string[]>([]);

  const entityIDs = useMemo(() => mapBy(entities, "id"), [entities]);

  const { users } = useUsers();
  const { codes, reload, isLoading } = useEntitiesCodes(
    isAdmin(user) ? undefined : entityIDs
  );

  const data: TableData[] = useMemo(
    () =>
      codes.map((code) => ({
        ...code,
        entity: findBy(entities, "id", code.entity),
        creator: findBy(users, "id", code.creator),
      })) as TableData[],
    [codes, entities, users]
  );

  const toggleCode = (id: string) => {
    setSelectedCodes((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]
    );
  };

  // const toggleAllCodes = (checked: boolean) => {
  // 	if (checked) return setSelectedCodes(visibleRows.filter((x) => !x.userId).map((x) => x.code));

  // 	return setSelectedCodes([]);
  // };

  const deleteCodes = async (codes: string[]) => {
    if (!canDeleteCodes) return;
    if (
      !confirm(`Are you sure you want to delete these ${codes.length} code(s)?`)
    )
      return;

    const params = new URLSearchParams();
    codes.forEach((code) => params.append("code", code));

    axios
      .delete(`/api/code?${params.toString()}`)
      .then(() => {
        toast.success(`Deleted the codes!`);
        setSelectedCodes([]);
      })
      .catch((reason) => {
        if (reason.response.status === 404) {
          toast.error("Code not found!");
          return;
        }

        if (reason.response.status === 403) {
          toast.error("You do not have permission to delete this code!");
          return;
        }

        toast.error("Something went wrong, please try again later.");
      })
      .finally(reload);
  };

  const deleteCode = async (code: Code) => {
    if (!canDeleteCodes) return;
    if (!confirm(`Are you sure you want to delete this "${code.code}" code?`))
      return;

    axios
      .delete(`/api/code/${code.code}`)
      .then(() => toast.success(`Deleted the "${code.code}" exam`))
      .catch((reason) => {
        if (reason.response.status === 404) {
          toast.error("Code not found!");
          return;
        }

        if (reason.response.status === 403) {
          toast.error("You do not have permission to delete this code!");
          return;
        }

        toast.error("Something went wrong, please try again later.");
      })
      .finally(reload);
  };

  const defaultColumns = [
    columnHelper.accessor("code", {
      id: "codeCheckbox",
      enableSorting: false,
      header: () => "",
      cell: (info) =>
        !info.row.original.userId ? (
          <Checkbox
            isChecked={selectedCodes.includes(info.getValue())}
            onChange={() => toggleCode(info.getValue())}
          >
            {""}
          </Checkbox>
        ) : null,
    }),
    columnHelper.accessor("code", {
      header: "Code",
      cell: (info) => info.getValue(),
    }),
    columnHelper.accessor("creationDate", {
      header: "Creation Date",
      cell: (info) =>
        info.getValue() ? moment(info.getValue()).format("DD/MM/YYYY") : "N/A",
    }),
    columnHelper.accessor("email", {
      header: "E-mail",
      cell: (info) => info.getValue() || "N/A",
    }),
    columnHelper.accessor("creator", {
      header: "Creator",
      cell: (info) =>
        info.getValue()
          ? `${info.getValue().name} (${
              USER_TYPE_LABELS[info.getValue().type]
            })`
          : "N/A",
    }),
    columnHelper.accessor("entity", {
      header: "Entity",
      cell: (info) => info.getValue()?.label || "N/A",
    }),
    columnHelper.accessor("userId", {
      header: "Availability",
      cell: (info) =>
        info.getValue() ? (
          <span className="flex gap-1 items-center text-mti-green">
            <div className="w-2 h-2 rounded-full bg-mti-green" /> In Use
          </span>
        ) : (
          <span className="flex gap-1 items-center text-mti-red">
            <div className="w-2 h-2 rounded-full bg-mti-red" /> Unused
          </span>
        ),
    }),
    {
      header: "",
      id: "actions",
      cell: ({ row }: { row: { original: Code } }) => {
        return (
          <div className="flex gap-4">
            {canDeleteCodes && !row.original.userId && (
              <div
                data-tip="Delete"
                className="cursor-pointer tooltip"
                onClick={() => deleteCode(row.original)}
              >
                <BsTrash className="hover:text-mti-purple-light transition ease-in-out duration-300" />
              </div>
            )}
          </div>
        );
      },
    },
  ];

  return (
    <>
      <div className="flex items-center justify-between pb-4 pt-1">
        {canDeleteCodes && (
          <div className="flex gap-4 items-center w-full justify-end">
            <span>{selectedCodes.length} code(s) selected</span>
            <Button
              disabled={selectedCodes.length === 0}
              variant="outline"
              color="red"
              className="!py-1 px-10"
              onClick={() => deleteCodes(selectedCodes)}
            >
              Delete
            </Button>
          </div>
        )}
      </div>
      <Table<TableData>
        data={data}
        columns={defaultColumns}
        isLoading={isLoading}
        searchFields={[
          ["code"],
          ["email"],
          ["entity", "label"],
          ["creator", "name"],
          ["creator", "type"],
        ]}
      />
    </>
  );
}
