import Button from "@/components/Low/Button";
import Checkbox from "@/components/Low/Checkbox";
import { PERMISSIONS } from "@/constants/userPermissions";
import { CorporateUser, TeacherUser, Type, User } from "@/interfaces/user";
import { USER_TYPE_LABELS } from "@/resources/user";
import axios from "axios";
import clsx from "clsx";
import { capitalize, uniqBy } from "lodash";
import moment from "moment";
import { useEffect, useState } from "react";
import ReactDatePicker from "react-datepicker";
import { toast } from "react-toastify";
import ShortUniqueId from "short-unique-id";
import { checkAccess, getTypesOfUser } from "@/utils/permissions";
import { PermissionType } from "@/interfaces/permissions";
import usePermissions from "@/hooks/usePermissions";
import Input from "@/components/Low/Input";
import CountrySelect from "@/components/Low/CountrySelect";
import useGroups from "@/hooks/useGroups";
import useUsers from "@/hooks/useUsers";
import { getUserName } from "@/utils/users";
import Select from "@/components/Low/Select";
import { EntityWithRoles } from "@/interfaces/entity";
import useEntitiesGroups from "@/hooks/useEntitiesGroups";

const USER_TYPE_PERMISSIONS: {
  [key in Type]: { perm: PermissionType | undefined; list: Type[] };
} = {
  student: {
    perm: "createCodeStudent",
    list: [],
  },
  teacher: {
    perm: "createCodeTeacher",
    list: [],
  },
  agent: {
    perm: "createCodeCountryManager",
    list: ["student", "teacher", "corporate", "mastercorporate"],
  },
  corporate: {
    perm: "createCodeCorporate",
    list: ["student", "teacher"],
  },
  mastercorporate: {
    perm: undefined,
    list: ["student", "teacher", "corporate"],
  },
  admin: {
    perm: "createCodeAdmin",
    list: ["student", "teacher", "agent", "corporate", "admin", "mastercorporate"],
  },
  developer: {
    perm: undefined,
    list: ["student", "teacher", "agent", "corporate", "admin", "developer", "mastercorporate"],
  },
};

interface Props {
  user: User;
  users: User[];
  entities: EntityWithRoles[]
  permissions: PermissionType[];
  onFinish: () => void;
}

export default function UserCreator({ user, users, entities = [], permissions, onFinish }: Props) {
  const [name, setName] = useState<string>();
  const [email, setEmail] = useState<string>();
  const [phone, setPhone] = useState<string>();
  const [passportID, setPassportID] = useState<string>();
  const [studentID, setStudentID] = useState<string>();
  const [country, setCountry] = useState(user?.demographicInformation?.country);
  const [group, setGroup] = useState<string | null>();
  const [password, setPassword] = useState<string>();
  const [confirmPassword, setConfirmPassword] = useState<string>();
  const [expiryDate, setExpiryDate] = useState<Date | null>(
    user?.subscriptionExpirationDate ? moment(user?.subscriptionExpirationDate).toDate() : null,
  );
  const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true);
  const [isLoading, setIsLoading] = useState(false);
  const [type, setType] = useState<Type>("student");
  const [position, setPosition] = useState<string>();
  const [entity, setEntity] = useState((entities || [])[0]?.id || undefined)

  const { groups } = useEntitiesGroups();

  useEffect(() => {
    if (!isExpiryDateEnabled) setExpiryDate(null);
  }, [isExpiryDateEnabled]);

  const createUser = () => {
    if (!name || name.trim().length === 0) return toast.error("Please enter a valid name!");
    if (!email || email.trim().length === 0) return toast.error("Please enter a valid e-mail address!");
    if (users.map((x) => x.email).includes(email.trim())) return toast.error("That e-mail is already in use!");
    if (!password || password.trim().length < 6) return toast.error("Please enter a valid password!");
    if (password !== confirmPassword) return toast.error("The passwords do not match!");

    setIsLoading(true);

    const body = {
      name,
      email,
      password,
      groupID: group,
      entity,
      type,
      studentID: type === "student" ? studentID : undefined,
      expiryDate,
      demographicInformation: {
        passport_id: type === "student" ? passportID : undefined,
        phone,
        country,
        position,
      },
    };

    axios
      .post("/api/make_user", body)
      .then(() => {
        toast.success("That user has been created!");
        onFinish();

        setName("");
        setEmail("");
        setPhone("");
        setPassportID("");
        setStudentID("");
        setCountry(user?.demographicInformation?.country);
        setGroup(null);
        setEntity((entities || [])[0]?.id || undefined)
        setExpiryDate(user?.subscriptionExpirationDate ? moment(user?.subscriptionExpirationDate).toDate() : null);
        setIsExpiryDateEnabled(true);
        setType("student");
        setPosition(undefined);
      })
      .catch((error) => {
        const data = error?.response?.data;
        if (!!data?.message) return toast.error(data.message);
        toast.error("Something went wrong! Please try again later!");
      })
      .finally(() => setIsLoading(false));
  };

  return (
    <div className="flex flex-col gap-4 border p-4 border-mti-gray-platinum rounded-xl">
      <div className="grid grid-cols-2 gap-4">
        <Input required label="Name" value={name} onChange={setName} type="text" name="name" placeholder="Name" />
        <Input label="E-mail" required value={email} onChange={setEmail} type="email" name="email" placeholder="E-mail" />

        <Input type="password" name="password" label="Password" value={password} onChange={setPassword} placeholder="Password" required />
        <Input
          type="password"
          name="confirmPassword"
          label="Confirm Password"
          value={confirmPassword}
          onChange={setConfirmPassword}
          placeholder="ConfirmPassword"
          required
        />

        <div className="flex flex-col gap-4">
          <label className="font-normal text-base text-mti-gray-dim">Country *</label>
          <CountrySelect value={country} onChange={setCountry} />
        </div>

        <Input type="tel" name="phone" label="Phone number" value={phone} onChange={setPhone} placeholder="Phone number" required />

        {type === "student" && (
          <>
            <Input
              type="text"
              name="passport_id"
              label="Passport/National ID"
              onChange={setPassportID}
              value={passportID}
              placeholder="National ID or Passport number"
              required
            />
            <Input type="text" name="studentID" label="Student ID" onChange={setStudentID} value={studentID} placeholder="Student ID" />
          </>
        )}

        <div className={clsx("flex flex-col gap-4")}>
          <label className="font-normal text-base text-mti-gray-dim">Entity</label>
          <Select
            defaultValue={{ value: (entities || [])[0]?.id, label: (entities || [])[0]?.label }}
            options={entities.map((e) => ({ value: e.id, label: e.label }))}
            onChange={(e) => setEntity(e?.value || undefined)}
            isClearable={checkAccess(user, ["admin", "developer"])}
          />
        </div>

        {["corporate", "mastercorporate"].includes(type) && (
          <Input type="text" name="department" label="Department" onChange={setPosition} value={position} placeholder="Department" />
        )}

        <div className={clsx("flex flex-col gap-4")}>
          <label className="font-normal text-base text-mti-gray-dim">Group</label>
          <Select
            options={groups
              .filter((x) => x.entity?.id === entity)
              .map((g) => ({ value: g.id, label: g.name }))}
            onChange={(e) => setGroup(e?.value || undefined)}
            isClearable
          />
        </div>

        <div
          className={clsx(
            "flex flex-col gap-4",
            !checkAccess(user, ["developer", "admin", "corporate", "mastercorporate"]) && "col-span-2",
          )}>
          <label className="font-normal text-base text-mti-gray-dim">Type</label>
          {user && (
            <select
              defaultValue="student"
              value={type}
              onChange={(e) => setType(e.target.value as Type)}
              className="p-6 w-full min-w-[350px] min-h-[70px] flex justify-center text-sm font-normal rounded-full border focus:outline-none cursor-pointer bg-white">
              {Object.keys(USER_TYPE_LABELS)
                .filter((x) => {
                  const { list, perm } = USER_TYPE_PERMISSIONS[x as Type];
                  return checkAccess(user, getTypesOfUser(list), permissions, perm);
                })
                .map((type) => (
                  <option key={type} value={type}>
                    {USER_TYPE_LABELS[type as keyof typeof USER_TYPE_LABELS]}
                  </option>
                ))}
            </select>
          )}
        </div>

        <div className="flex flex-col gap-4">
          {user && checkAccess(user, ["developer", "admin", "corporate", "mastercorporate"]) && (
            <>
              <div className="-md:flex-row -md:items-center flex justify-between gap-2 md:flex-col 2xl:flex-row 2xl:items-center">
                <label className="text-mti-gray-dim text-base font-normal">Expiry Date</label>
                <Checkbox
                  isChecked={isExpiryDateEnabled}
                  onChange={setIsExpiryDateEnabled}
                  disabled={!!user?.subscriptionExpirationDate}>
                  Enabled
                </Checkbox>
              </div>
              {isExpiryDateEnabled && (
                <ReactDatePicker
                  className={clsx(
                    "flex min-h-[70px] w-full cursor-pointer justify-center rounded-full border p-6 text-sm font-normal focus:outline-none",
                    "hover:border-mti-purple tooltip",
                    "transition duration-300 ease-in-out",
                  )}
                  filterDate={(date) =>
                    moment(date).isAfter(new Date()) &&
                    (user?.subscriptionExpirationDate ? moment(date).isBefore(user?.subscriptionExpirationDate) : true)
                  }
                  dateFormat="dd/MM/yyyy"
                  selected={expiryDate}
                  onChange={(date) => setExpiryDate(date)}
                />
              )}
            </>
          )}
        </div>
      </div>

      <Button onClick={createUser} isLoading={isLoading} disabled={(isExpiryDateEnabled ? !expiryDate : false) || isLoading}>
        Create User
      </Button>
    </div>
  );
}
